Merge "Use audio_session_t consistently" into nyc-dev
diff --git a/Android.mk b/Android.mk
index 08f3468..cf6d946 100644
--- a/Android.mk
+++ b/Android.mk
@@ -42,7 +42,7 @@
 
 # EventLogTags files.
 LOCAL_SRC_FILES += \
-       core/java/android/auditing/SecurityLogTags.logtags \
+       core/java/android/app/admin/SecurityLogTags.logtags \
        core/java/android/content/EventLogTags.logtags \
        core/java/android/speech/tts/EventLogTags.logtags \
        core/java/android/webkit/EventLogTags.logtags \
@@ -117,6 +117,7 @@
 	core/java/android/bluetooth/IBluetoothManager.aidl \
 	core/java/android/bluetooth/IBluetoothManagerCallback.aidl \
 	core/java/android/bluetooth/IBluetoothPbap.aidl \
+	core/java/android/bluetooth/IBluetoothPbapClient.aidl \
 	core/java/android/bluetooth/IBluetoothMap.aidl \
 	core/java/android/bluetooth/IBluetoothSap.aidl \
 	core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \
@@ -413,6 +414,8 @@
 	telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl \
 	telephony/java/com/android/ims/internal/IImsEcbm.aidl \
 	telephony/java/com/android/ims/internal/IImsEcbmListener.aidl \
+        telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl \
+        telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl \
 	telephony/java/com/android/ims/internal/IImsService.aidl \
 	telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl \
 	telephony/java/com/android/ims/internal/IImsUt.aidl \
@@ -827,6 +830,7 @@
     -since $(SRC_API_DIR)/21.txt 21 \
     -since $(SRC_API_DIR)/22.txt 22 \
     -since $(SRC_API_DIR)/23.txt 23 \
+    -since ./frameworks/base/api/current.txt N \
 		-werror -hide 111 -hide 113 \
 		-overview $(LOCAL_PATH)/core/java/overview.html
 
@@ -870,9 +874,11 @@
 framework_docs_SDK_REL_ID:=1
 
 framework_docs_LOCAL_DROIDDOC_OPTIONS += \
+		-hdf sdk.codename N \
+		-hdf sdk.preview.version 2 \
 		-hdf sdk.version $(framework_docs_SDK_VERSION) \
 		-hdf sdk.rel.id $(framework_docs_SDK_REL_ID) \
-		-hdf sdk.preview 0
+		-hdf sdk.preview 1
 
 # ====  the api stubs and current.xml ===========================
 include $(CLEAR_VARS)
@@ -1027,23 +1033,24 @@
 		-offlinemode \
 		-title "Android SDK" \
 		-proofread $(OUT_DOCS)/$(LOCAL_MODULE)-proofread.txt \
-		-todo $(OUT_DOCS)/$(LOCAL_MODULE)-docs-todo.html \
 		-sdkvalues $(OUT_DOCS) \
-		-hdf android.whichdoc offline
+		-hdf android.whichdoc offline \
+		-referenceonly
 
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk-refonly
 
 include $(BUILD_DROIDDOC)
 
 static_doc_index_redirect := $(out_dir)/index.html
 $(static_doc_index_redirect): \
-	$(LOCAL_PATH)/docs/docs-documentation-redirect.html | $(ACP)
+	$(LOCAL_PATH)/docs/docs-preview-index.html | $(ACP)
 	$(hide) mkdir -p $(dir $@)
 	$(hide) $(ACP) $< $@
 
 $(full_target): $(static_doc_index_redirect)
 $(full_target): $(framework_built)
 
+
 # ==== docs for the web (on the androiddevdocs app engine server) =======================
 include $(CLEAR_VARS)
 
diff --git a/api/current.txt b/api/current.txt
index 10de28d..649c4b6a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -559,6 +559,7 @@
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillColor = 16843780; // 0x1010404
     field public static final int fillEnabled = 16843343; // 0x101024f
+    field public static final int fillType = 16844064; // 0x1010520
     field public static final int fillViewport = 16843130; // 0x101017a
     field public static final int filter = 16843035; // 0x101011b
     field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -879,6 +880,7 @@
     field public static final int nextFocusLeft = 16842977; // 0x10100e1
     field public static final int nextFocusRight = 16842978; // 0x10100e2
     field public static final int nextFocusUp = 16842979; // 0x10100e3
+    field public static final int nfcAntennaPositionDrawable = 16844063; // 0x101051f
     field public static final int noHistory = 16843309; // 0x101022d
     field public static final int normalScreens = 16843397; // 0x1010285
     field public static final int notificationTimeout = 16843651; // 0x1010383
@@ -3441,7 +3443,7 @@
     method public android.view.View getCurrentFocus();
     method public android.app.FragmentManager getFragmentManager();
     method public android.content.Intent getIntent();
-    method public deprecated java.lang.Object getLastNonConfigurationInstance();
+    method public java.lang.Object getLastNonConfigurationInstance();
     method public android.view.LayoutInflater getLayoutInflater();
     method public android.app.LoaderManager getLoaderManager();
     method public java.lang.String getLocalClassName();
@@ -3535,14 +3537,13 @@
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public void onProvideAssistContent(android.app.assist.AssistContent);
     method public void onProvideAssistData(android.os.Bundle);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public android.net.Uri onProvideReferrer();
     method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
     method protected void onRestart();
     method protected void onRestoreInstanceState(android.os.Bundle);
     method public void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method protected void onResume();
-    method public deprecated java.lang.Object onRetainNonConfigurationInstance();
+    method public java.lang.Object onRetainNonConfigurationInstance();
     method protected void onSaveInstanceState(android.os.Bundle);
     method public void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -4217,7 +4218,6 @@
     method public void onPanelClosed(int, android.view.Menu);
     method public boolean onPrepareOptionsMenu(android.view.Menu);
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public void onRestoreInstanceState(android.os.Bundle);
     method public android.os.Bundle onSaveInstanceState();
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -5851,7 +5851,6 @@
     method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName);
     method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
-    method public boolean getDeviceLoggingEnabled(android.content.ComponentName);
     method public java.lang.String getDeviceOwnerLockScreenInfo();
     method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
@@ -5900,6 +5899,7 @@
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isProfileOwnerApp(java.lang.String);
     method public boolean isProvisioningAllowed(java.lang.String);
+    method public boolean isSecurityLoggingEnabled(android.content.ComponentName);
     method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String);
     method public void lockNow();
     method public void reboot(android.content.ComponentName);
@@ -5909,8 +5909,8 @@
     method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
     method public boolean requestBugreport(android.content.ComponentName);
     method public boolean resetPassword(java.lang.String, int);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrieveDeviceLogs(android.content.ComponentName);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrievePreviousDeviceLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
     method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
     method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
     method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
@@ -5922,7 +5922,6 @@
     method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
     method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
     method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean);
-    method public void setDeviceLoggingEnabled(android.content.ComponentName, boolean);
     method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String);
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
@@ -5955,6 +5954,7 @@
     method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
     method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+    method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean);
     method public void setShortSupportMessage(android.content.ComponentName, java.lang.String);
     method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
@@ -5978,6 +5978,7 @@
     field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
     field public static final int ENCRYPTION_STATUS_ACTIVE = 3; // 0x3
     field public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4; // 0x4
+    field public static final int ENCRYPTION_STATUS_ACTIVE_PER_USER = 5; // 0x5
     field public static final int ENCRYPTION_STATUS_INACTIVE = 1; // 0x1
     field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0
     field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
@@ -6039,6 +6040,27 @@
     field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
   }
 
+  public class SecurityLog {
+    ctor public SecurityLog();
+    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
+    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
+    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
+    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
+    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
+    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
+    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
+  }
+
+  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.Object getData();
+    method public int getTag();
+    method public long getTimeNanos();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.admin.SecurityLog.SecurityEvent> CREATOR;
+  }
+
   public class SystemUpdatePolicy implements android.os.Parcelable {
     method public static android.app.admin.SystemUpdatePolicy createAutomaticInstallPolicy();
     method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy();
@@ -6371,8 +6393,8 @@
     method public long getTxPackets();
     method public int getUid();
     field public static final int ROAMING_ALL = -1; // 0xffffffff
-    field public static final int ROAMING_DEFAULT = 1; // 0x1
-    field public static final int ROAMING_ROAMING = 2; // 0x2
+    field public static final int ROAMING_NO = 1; // 0x1
+    field public static final int ROAMING_YES = 2; // 0x2
     field public static final int STATE_ALL = -1; // 0xffffffff
     field public static final int STATE_DEFAULT = 1; // 0x1
     field public static final int STATE_FOREGROUND = 2; // 0x2
@@ -6579,31 +6601,6 @@
 
 }
 
-package android.auditing {
-
-  public class SecurityLog {
-    ctor public SecurityLog();
-    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
-    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
-    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
-    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
-    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
-    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
-    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
-    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
-  }
-
-  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public java.lang.Object getData();
-    method public int getTag();
-    method public long getTimeNanos();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.auditing.SecurityLog.SecurityEvent> CREATOR;
-  }
-
-}
-
 package android.bluetooth {
 
   public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
@@ -8112,7 +8109,7 @@
     field public static final java.lang.String DOWNLOAD_SERVICE = "download";
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
     field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
-    field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardwareproperties";
+    field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
     field public static final java.lang.String INPUT_SERVICE = "input";
     field public static final java.lang.String JOB_SCHEDULER_SERVICE = "jobscheduler";
@@ -8142,6 +8139,7 @@
     field public static final java.lang.String SENSOR_SERVICE = "sensor";
     field public static final java.lang.String SHORTCUT_SERVICE = "shortcut";
     field public static final java.lang.String STORAGE_SERVICE = "storage";
+    field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth";
     field public static final java.lang.String TELECOM_SERVICE = "telecom";
     field public static final java.lang.String TELEPHONY_SERVICE = "phone";
     field public static final java.lang.String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
@@ -9325,6 +9323,7 @@
     field public int flags;
     field public int largestWidthLimitDp;
     field public java.lang.String manageSpaceActivityName;
+    field public java.lang.String minSdkVersion;
     field public java.lang.String nativeLibraryDir;
     field public java.lang.String permission;
     field public java.lang.String processName;
@@ -9450,6 +9449,7 @@
     method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
+    method public boolean hasShortcutHostPermission();
     method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
     method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
     method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
@@ -9560,6 +9560,7 @@
     method public java.lang.String[] getNames() throws java.io.IOException;
     method public java.io.InputStream openRead(java.lang.String) throws java.io.IOException;
     method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
+    method public void removeSplit(java.lang.String) throws java.io.IOException;
     method public void setStagingProgress(float);
   }
 
@@ -9994,6 +9995,7 @@
     method public int getWeight();
     method public boolean hasIconFile();
     method public boolean hasIconResource();
+    method public boolean hasKeyFieldsOnly();
     method public boolean isDynamic();
     method public boolean isPinned();
     method public void writeToParcel(android.os.Parcel, int);
@@ -10004,6 +10006,7 @@
     field public static final int FLAG_DYNAMIC = 1; // 0x1
     field public static final int FLAG_HAS_ICON_FILE = 8; // 0x8
     field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
+    field public static final int FLAG_KEY_FIELDS_ONLY = 16; // 0x10
     field public static final int FLAG_PINNED = 2; // 0x2
   }
 
@@ -10024,6 +10027,7 @@
     method public void deleteAllDynamicShortcuts();
     method public void deleteDynamicShortcut(java.lang.String);
     method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
+    method public int getIconMaxDimensions();
     method public int getMaxDynamicShortcutCount();
     method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
     method public long getRateLimitResetTime();
@@ -10108,7 +10112,6 @@
     method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
-    method public int getChangingConfigurations();
     method public int getColorForState(int[], int);
     method public int getDefaultColor();
     method public boolean isOpaque();
@@ -10120,6 +10123,7 @@
 
   public abstract class ComplexColor {
     ctor public ComplexColor();
+    method public int getChangingConfigurations();
     method public abstract int getDefaultColor();
     method public boolean isStateful();
   }
@@ -11467,17 +11471,6 @@
 
 package android.graphics {
 
-  public deprecated class AvoidXfermode extends android.graphics.Xfermode {
-    ctor public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode);
-  }
-
-  public static final class AvoidXfermode.Mode extends java.lang.Enum {
-    method public static android.graphics.AvoidXfermode.Mode valueOf(java.lang.String);
-    method public static final android.graphics.AvoidXfermode.Mode[] values();
-    enum_constant public static final android.graphics.AvoidXfermode.Mode AVOID;
-    enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET;
-  }
-
   public final class Bitmap implements android.os.Parcelable {
     method public boolean compress(android.graphics.Bitmap.CompressFormat, int, java.io.OutputStream);
     method public android.graphics.Bitmap copy(android.graphics.Bitmap.Config, boolean);
@@ -12344,10 +12337,6 @@
     field public int bytesPerPixel;
   }
 
-  public deprecated class PixelXorXfermode extends android.graphics.Xfermode {
-    ctor public PixelXorXfermode(int);
-  }
-
   public class Point implements android.os.Parcelable {
     ctor public Point();
     ctor public Point(int, int);
@@ -12907,7 +12896,8 @@
     method public int getGradientType();
     method public int getOpacity();
     method public android.graphics.drawable.GradientDrawable.Orientation getOrientation();
-    method public boolean isUseLevel();
+    method public int getShape();
+    method public boolean getUseLevel();
     method public void setAlpha(int);
     method public void setColor(int);
     method public void setColor(android.content.res.ColorStateList);
@@ -13026,9 +13016,9 @@
     method public void setPaddingMode(int);
     method public void setPaddingRelative(int, int, int, int);
     method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+    field public static final int INSET_UNDEFINED = -2147483648; // 0x80000000
     field public static final int PADDING_MODE_NEST = 0; // 0x0
     field public static final int PADDING_MODE_STACK = 1; // 0x1
-    field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000
   }
 
   public class LevelListDrawable extends android.graphics.drawable.DrawableContainer {
@@ -13769,6 +13759,7 @@
 
   public static abstract class CameraCaptureSession.CaptureCallback {
     ctor public CameraCaptureSession.CaptureCallback();
+    method public void onCaptureBufferLost(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.view.Surface, long);
     method public void onCaptureCompleted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult);
     method public void onCaptureFailed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureFailure);
     method public void onCaptureProgressed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
@@ -19242,24 +19233,6 @@
     method public boolean hasFullBiasNanos();
     method public boolean hasLeapSecond();
     method public boolean hasTimeUncertaintyNanos();
-    method public void reset();
-    method public void resetBiasNanos();
-    method public void resetBiasUncertaintyNanos();
-    method public void resetDriftNanosPerSecond();
-    method public void resetDriftUncertaintyNanosPerSecond();
-    method public void resetFullBiasNanos();
-    method public void resetLeapSecond();
-    method public void resetTimeUncertaintyNanos();
-    method public void set(android.location.GnssClock);
-    method public void setBiasNanos(double);
-    method public void setBiasUncertaintyNanos(double);
-    method public void setDriftNanosPerSecond(double);
-    method public void setDriftUncertaintyNanosPerSecond(double);
-    method public void setFullBiasNanos(long);
-    method public void setHardwareClockDiscontinuityCount(int);
-    method public void setLeapSecond(int);
-    method public void setTimeNanos(long);
-    method public void setTimeUncertaintyNanos(double);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
   }
@@ -19290,31 +19263,6 @@
     method public boolean hasCarrierPhaseUncertainty();
     method public boolean hasSnrInDb();
     method public boolean isPseudorangeRateCorrected();
-    method public void reset();
-    method public void resetCarrierCycles();
-    method public void resetCarrierFrequencyHz();
-    method public void resetCarrierPhase();
-    method public void resetCarrierPhaseUncertainty();
-    method public void resetSnrInDb();
-    method public void set(android.location.GnssMeasurement);
-    method public void setAccumulatedDeltaRangeMeters(double);
-    method public void setAccumulatedDeltaRangeState(int);
-    method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
-    method public void setCarrierCycles(long);
-    method public void setCarrierFrequencyHz(float);
-    method public void setCarrierPhase(double);
-    method public void setCarrierPhaseUncertainty(double);
-    method public void setCn0DbHz(double);
-    method public void setConstellationType(int);
-    method public void setMultipathIndicator(int);
-    method public void setPseudorangeRateMetersPerSecond(double);
-    method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
-    method public void setReceivedSvTimeNanos(long);
-    method public void setReceivedSvTimeUncertaintyNanos(long);
-    method public void setSnrInDb(double);
-    method public void setState(int);
-    method public void setSvid(int);
-    method public void setTimeOffsetNanos(double);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
     field public static final int ADR_STATE_RESET = 2; // 0x2
@@ -19364,14 +19312,6 @@
     method public int getSubmessageId();
     method public int getSvid();
     method public int getType();
-    method public void reset();
-    method public void set(android.location.GnssNavigationMessage);
-    method public void setData(byte[]);
-    method public void setMessageId(int);
-    method public void setStatus(int);
-    method public void setSubmessageId(int);
-    method public void setSvid(int);
-    method public void setType(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
     field public static final int STATUS_PARITY_PASSED = 1; // 0x1
@@ -20227,37 +20167,129 @@
     field public static final int ORIENTATION_TRANSVERSE = 7; // 0x7
     field public static final int ORIENTATION_UNDEFINED = 0; // 0x0
     field public static final java.lang.String TAG_APERTURE = "FNumber";
+    field public static final java.lang.String TAG_APERTURE_VALUE = "ApertureValue";
+    field public static final java.lang.String TAG_ARTIST = "Artist";
+    field public static final java.lang.String TAG_BITS_PER_SAMPLE = "BitsPerSample";
+    field public static final java.lang.String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
+    field public static final java.lang.String TAG_CFA_PATTERN = "CFAPattern";
+    field public static final java.lang.String TAG_COLOR_SPACE = "ColorSpace";
+    field public static final java.lang.String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
+    field public static final java.lang.String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
+    field public static final java.lang.String TAG_COMPRESSION = "Compression";
+    field public static final java.lang.String TAG_CONTRAST = "Contrast";
+    field public static final java.lang.String TAG_COPYRIGHT = "Copyright";
+    field public static final java.lang.String TAG_CUSTOM_RENDERED = "CustomRendered";
     field public static final java.lang.String TAG_DATETIME = "DateTime";
     field public static final java.lang.String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    field public static final java.lang.String TAG_DATETIME_ORIGINAL = "DateTimeOriginal";
+    field public static final java.lang.String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription";
     field public static final java.lang.String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+    field public static final java.lang.String TAG_EXIF_VERSION = "ExifVersion";
     field public static final java.lang.String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+    field public static final java.lang.String TAG_EXPOSURE_INDEX = "ExposureIndex";
     field public static final java.lang.String TAG_EXPOSURE_MODE = "ExposureMode";
     field public static final java.lang.String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
     field public static final java.lang.String TAG_EXPOSURE_TIME = "ExposureTime";
+    field public static final java.lang.String TAG_FILE_SOURCE = "FileSource";
     field public static final java.lang.String TAG_FLASH = "Flash";
+    field public static final java.lang.String TAG_FLASHPIX_VERSION = "FlashpixVersion";
+    field public static final java.lang.String TAG_FLASH_ENERGY = "FlashEnergy";
     field public static final java.lang.String TAG_FOCAL_LENGTH = "FocalLength";
+    field public static final java.lang.String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm";
+    field public static final java.lang.String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit";
+    field public static final java.lang.String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution";
+    field public static final java.lang.String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
+    field public static final java.lang.String TAG_F_NUMBER = "FNumber";
+    field public static final java.lang.String TAG_GAIN_CONTROL = "GainControl";
     field public static final java.lang.String TAG_GPS_ALTITUDE = "GPSAltitude";
     field public static final java.lang.String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
+    field public static final java.lang.String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
     field public static final java.lang.String TAG_GPS_DATESTAMP = "GPSDateStamp";
+    field public static final java.lang.String TAG_GPS_DEST_BEARING = "GPSDestBearing";
+    field public static final java.lang.String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef";
+    field public static final java.lang.String TAG_GPS_DEST_DISTANCE = "GPSDestDistance";
+    field public static final java.lang.String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef";
+    field public static final java.lang.String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude";
+    field public static final java.lang.String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef";
+    field public static final java.lang.String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude";
+    field public static final java.lang.String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
+    field public static final java.lang.String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
+    field public static final java.lang.String TAG_GPS_DOP = "GPSDOP";
+    field public static final java.lang.String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
+    field public static final java.lang.String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
     field public static final java.lang.String TAG_GPS_LATITUDE = "GPSLatitude";
     field public static final java.lang.String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
     field public static final java.lang.String TAG_GPS_LONGITUDE = "GPSLongitude";
     field public static final java.lang.String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    field public static final java.lang.String TAG_GPS_MAP_DATUM = "GPSMapDatum";
+    field public static final java.lang.String TAG_GPS_MEASURE_MODE = "GPSMeasureMode";
     field public static final java.lang.String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
+    field public static final java.lang.String TAG_GPS_SATELLITES = "GPSSatellites";
+    field public static final java.lang.String TAG_GPS_SPEED = "GPSSpeed";
+    field public static final java.lang.String TAG_GPS_SPEED_REF = "GPSSpeedRef";
+    field public static final java.lang.String TAG_GPS_STATUS = "GPSStatus";
     field public static final java.lang.String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+    field public static final java.lang.String TAG_GPS_TRACK = "GPSTrack";
+    field public static final java.lang.String TAG_GPS_TRACK_REF = "GPSTrackRef";
+    field public static final java.lang.String TAG_GPS_VERSION_ID = "GPSVersionID";
+    field public static final java.lang.String TAG_IMAGE_DESCRIPTION = "ImageDescription";
     field public static final java.lang.String TAG_IMAGE_LENGTH = "ImageLength";
+    field public static final java.lang.String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
     field public static final java.lang.String TAG_IMAGE_WIDTH = "ImageWidth";
+    field public static final java.lang.String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
     field public static final java.lang.String TAG_ISO = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
+    field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
     field public static final java.lang.String TAG_LIGHT_SOURCE = "LightSource";
     field public static final java.lang.String TAG_MAKE = "Make";
+    field public static final java.lang.String TAG_MAKER_NOTE = "MakerNote";
+    field public static final java.lang.String TAG_MAX_APERTURE_VALUE = "MaxApertureValue";
     field public static final java.lang.String TAG_METERING_MODE = "MeteringMode";
     field public static final java.lang.String TAG_MODEL = "Model";
+    field public static final java.lang.String TAG_OECF = "OECF";
     field public static final java.lang.String TAG_ORIENTATION = "Orientation";
+    field public static final java.lang.String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
+    field public static final java.lang.String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
+    field public static final java.lang.String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
+    field public static final java.lang.String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
+    field public static final java.lang.String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
+    field public static final java.lang.String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
+    field public static final java.lang.String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
+    field public static final java.lang.String TAG_RESOLUTION_UNIT = "ResolutionUnit";
+    field public static final java.lang.String TAG_ROWS_PER_STRIP = "RowsPerStrip";
+    field public static final java.lang.String TAG_SAMPLES_PER_PIXEL = "SamplesPerPixel";
+    field public static final java.lang.String TAG_SATURATION = "Saturation";
+    field public static final java.lang.String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
+    field public static final java.lang.String TAG_SCENE_TYPE = "SceneType";
+    field public static final java.lang.String TAG_SENSING_METHOD = "SensingMethod";
+    field public static final java.lang.String TAG_SHARPNESS = "Sharpness";
+    field public static final java.lang.String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
+    field public static final java.lang.String TAG_SOFTWARE = "Software";
+    field public static final java.lang.String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
+    field public static final java.lang.String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
+    field public static final java.lang.String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
+    field public static final java.lang.String TAG_STRIP_OFFSETS = "StripOffsets";
+    field public static final java.lang.String TAG_SUBJECT_AREA = "SubjectArea";
     field public static final java.lang.String TAG_SUBJECT_DISTANCE = "SubjectDistance";
+    field public static final java.lang.String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange";
+    field public static final java.lang.String TAG_SUBJECT_LOCATION = "SubjectLocation";
     field public static final java.lang.String TAG_SUBSEC_TIME = "SubSecTime";
     field public static final java.lang.String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
+    field public static final java.lang.String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized";
     field public static final java.lang.String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
+    field public static final java.lang.String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
+    field public static final java.lang.String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
+    field public static final java.lang.String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
+    field public static final java.lang.String TAG_TRANSFER_FUNCTION = "TransferFunction";
+    field public static final java.lang.String TAG_USER_COMMENT = "UserComment";
     field public static final java.lang.String TAG_WHITE_BALANCE = "WhiteBalance";
+    field public static final java.lang.String TAG_WHITE_POINT = "WhitePoint";
+    field public static final java.lang.String TAG_X_RESOLUTION = "XResolution";
+    field public static final java.lang.String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients";
+    field public static final java.lang.String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
+    field public static final java.lang.String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
+    field public static final java.lang.String TAG_Y_RESOLUTION = "YResolution";
     field public static final int WHITEBALANCE_AUTO = 0; // 0x0
     field public static final int WHITEBALANCE_MANUAL = 1; // 0x1
   }
@@ -20983,6 +21015,7 @@
     field public static final java.lang.String KEY_DURATION = "durationUs";
     field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
     field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
+    field public static final java.lang.String KEY_HDR_STATIC_INFO = "hdr-static-info";
     field public static final java.lang.String KEY_HEIGHT = "height";
     field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
     field public static final java.lang.String KEY_IS_ADTS = "is-adts";
@@ -23052,6 +23085,7 @@
     method public void notifyError(int);
     method public void notifyRecordingStopped(android.net.Uri);
     method public void notifyTuned(android.net.Uri);
+    method public void onAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public abstract void onRelease();
     method public abstract void onStartRecording(android.net.Uri);
     method public abstract void onStopRecording();
@@ -23069,6 +23103,7 @@
     method public void notifyTracksChanged(java.util.List<android.media.tv.TvTrackInfo>);
     method public void notifyVideoAvailable();
     method public void notifyVideoUnavailable(int);
+    method public void onAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public android.view.View onCreateOverlayView();
     method public boolean onGenericMotionEvent(android.view.MotionEvent);
     method public boolean onKeyDown(int, android.view.KeyEvent);
@@ -23100,6 +23135,7 @@
   public class TvRecordingClient {
     ctor public TvRecordingClient(android.content.Context, java.lang.String, android.media.tv.TvRecordingClient.RecordingCallback, android.os.Handler);
     method public void release();
+    method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public void startRecording(android.net.Uri);
     method public void stopRecording();
     method public void tune(java.lang.String, android.net.Uri);
@@ -23161,6 +23197,7 @@
     method public boolean onUnhandledInputEvent(android.view.InputEvent);
     method public void reset();
     method public void selectTrack(int, java.lang.String);
+    method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public void setCallback(android.media.tv.TvView.TvInputCallback);
     method public void setCaptionEnabled(boolean);
     method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener);
@@ -29080,7 +29117,6 @@
     ctor public PersistableBundle();
     ctor public PersistableBundle(int);
     ctor public PersistableBundle(android.os.PersistableBundle);
-    ctor public PersistableBundle(android.os.Bundle);
     method public java.lang.Object clone();
     method public int describeContents();
     method public android.os.PersistableBundle getPersistableBundle(java.lang.String);
@@ -29409,6 +29445,147 @@
 
 }
 
+package android.os.health {
+
+  public class HealthStats {
+    method public java.lang.String getDataType();
+    method public long getMeasurement(int);
+    method public int getMeasurementKeyAt(int);
+    method public int getMeasurementKeyCount();
+    method public java.util.Map<java.lang.String, java.lang.Long> getMeasurements(int);
+    method public int getMeasurementsKeyAt(int);
+    method public int getMeasurementsKeyCount();
+    method public java.util.Map<java.lang.String, android.os.health.HealthStats> getStats(int);
+    method public int getStatsKeyAt(int);
+    method public int getStatsKeyCount();
+    method public android.os.health.TimerStat getTimer(int);
+    method public int getTimerCount(int);
+    method public int getTimerKeyAt(int);
+    method public int getTimerKeyCount();
+    method public long getTimerTime(int);
+    method public java.util.Map<java.lang.String, android.os.health.TimerStat> getTimers(int);
+    method public int getTimersKeyAt(int);
+    method public int getTimersKeyCount();
+    method public boolean hasMeasurement(int);
+    method public boolean hasMeasurements(int);
+    method public boolean hasStats(int);
+    method public boolean hasTimer(int);
+    method public boolean hasTimers(int);
+  }
+
+  public final class PackageHealthStats {
+    field public static final int MEASUREMENTS_WAKEUP_ALARMS_COUNT = 40002; // 0x9c42
+    field public static final int STATS_SERVICES = 40001; // 0x9c41
+  }
+
+  public final class PidHealthStats {
+    field public static final int MEASUREMENT_WAKE_NESTING_COUNT = 20001; // 0x4e21
+    field public static final int MEASUREMENT_WAKE_START_MS = 20003; // 0x4e23
+    field public static final int MEASUREMENT_WAKE_SUM_MS = 20002; // 0x4e22
+  }
+
+  public final class ProcessHealthStats {
+    field public static final int MEASUREMENT_ANR_COUNT = 30005; // 0x7535
+    field public static final int MEASUREMENT_CRASHES_COUNT = 30004; // 0x7534
+    field public static final int MEASUREMENT_FOREGROUND_MS = 30006; // 0x7536
+    field public static final int MEASUREMENT_STARTS_COUNT = 30003; // 0x7533
+    field public static final int MEASUREMENT_SYSTEM_TIME_MS = 30002; // 0x7532
+    field public static final int MEASUREMENT_USER_TIME_MS = 30001; // 0x7531
+  }
+
+  public final class ServiceHealthStats {
+    field public static final int MEASUREMENT_LAUNCH_COUNT = 50002; // 0xc352
+    field public static final int MEASUREMENT_START_SERVICE_COUNT = 50001; // 0xc351
+  }
+
+  public class SystemHealthManager {
+    method public static android.os.health.SystemHealthManager from(android.content.Context);
+    method public android.os.health.HealthStats takeMyUidSnapshot();
+    method public android.os.health.HealthStats takeUidSnapshot(int);
+    method public android.os.health.HealthStats[] takeUidSnapshots(int[]);
+  }
+
+  public class TimerStat implements android.os.Parcelable {
+    ctor public TimerStat();
+    ctor public TimerStat(int, long);
+    ctor public TimerStat(android.os.Parcel);
+    method public int describeContents();
+    method public int getCount();
+    method public long getTime();
+    method public void setCount(int);
+    method public void setTime(long);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.os.health.TimerStat> CREATOR;
+  }
+
+  public final class UidHealthStats {
+    field public static final int MEASUREMENT_BLUETOOTH_IDLE_MS = 10020; // 0x2724
+    field public static final int MEASUREMENT_BLUETOOTH_POWER_MAMS = 10023; // 0x2727
+    field public static final int MEASUREMENT_BLUETOOTH_RX_BYTES = 10052; // 0x2744
+    field public static final int MEASUREMENT_BLUETOOTH_RX_MS = 10021; // 0x2725
+    field public static final int MEASUREMENT_BLUETOOTH_RX_PACKETS = 10058; // 0x274a
+    field public static final int MEASUREMENT_BLUETOOTH_TX_BYTES = 10053; // 0x2745
+    field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
+    field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
+    field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
+    field public static final int MEASUREMENT_CPU_POWER_MAUS = 10064; // 0x2750
+    field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
+    field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
+    field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
+    field public static final int MEASUREMENT_MOBILE_RX_MS = 10025; // 0x2729
+    field public static final int MEASUREMENT_MOBILE_RX_PACKETS = 10054; // 0x2746
+    field public static final int MEASUREMENT_MOBILE_TX_BYTES = 10049; // 0x2741
+    field public static final int MEASUREMENT_MOBILE_TX_MS = 10026; // 0x272a
+    field public static final int MEASUREMENT_MOBILE_TX_PACKETS = 10055; // 0x2747
+    field public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = 10045; // 0x273d
+    field public static final int MEASUREMENT_REALTIME_BATTERY_MS = 10001; // 0x2711
+    field public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = 10003; // 0x2713
+    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = 10063; // 0x274f
+    field public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = 10047; // 0x273f
+    field public static final int MEASUREMENT_UPTIME_BATTERY_MS = 10002; // 0x2712
+    field public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = 10004; // 0x2714
+    field public static final int MEASUREMENT_USER_CPU_TIME_US = 10062; // 0x274e
+    field public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = 10029; // 0x272d
+    field public static final int MEASUREMENT_WIFI_IDLE_MS = 10016; // 0x2720
+    field public static final int MEASUREMENT_WIFI_MULTICAST_MS = 10031; // 0x272f
+    field public static final int MEASUREMENT_WIFI_POWER_MAMS = 10019; // 0x2723
+    field public static final int MEASUREMENT_WIFI_RUNNING_MS = 10028; // 0x272c
+    field public static final int MEASUREMENT_WIFI_RX_BYTES = 10050; // 0x2742
+    field public static final int MEASUREMENT_WIFI_RX_MS = 10017; // 0x2721
+    field public static final int MEASUREMENT_WIFI_RX_PACKETS = 10056; // 0x2748
+    field public static final int MEASUREMENT_WIFI_TX_BYTES = 10051; // 0x2743
+    field public static final int MEASUREMENT_WIFI_TX_MS = 10018; // 0x2722
+    field public static final int MEASUREMENT_WIFI_TX_PACKETS = 10057; // 0x2749
+    field public static final int STATS_PACKAGES = 10015; // 0x271f
+    field public static final int STATS_PIDS = 10013; // 0x271d
+    field public static final int STATS_PROCESSES = 10014; // 0x271e
+    field public static final int TIMERS_JOBS = 10010; // 0x271a
+    field public static final int TIMERS_SENSORS = 10012; // 0x271c
+    field public static final int TIMERS_SYNCS = 10009; // 0x2719
+    field public static final int TIMERS_WAKELOCKS_DRAW = 10008; // 0x2718
+    field public static final int TIMERS_WAKELOCKS_FULL = 10005; // 0x2715
+    field public static final int TIMERS_WAKELOCKS_PARTIAL = 10006; // 0x2716
+    field public static final int TIMERS_WAKELOCKS_WINDOW = 10007; // 0x2717
+    field public static final int TIMER_AUDIO = 10032; // 0x2730
+    field public static final int TIMER_BLUETOOTH_SCAN = 10037; // 0x2735
+    field public static final int TIMER_CAMERA = 10035; // 0x2733
+    field public static final int TIMER_FLASHLIGHT = 10034; // 0x2732
+    field public static final int TIMER_FOREGROUND_ACTIVITY = 10036; // 0x2734
+    field public static final int TIMER_GPS_SENSOR = 10011; // 0x271b
+    field public static final int TIMER_MOBILE_RADIO_ACTIVE = 10061; // 0x274d
+    field public static final int TIMER_PROCESS_STATE_BACKGROUND_MS = 10042; // 0x273a
+    field public static final int TIMER_PROCESS_STATE_CACHED_MS = 10043; // 0x273b
+    field public static final int TIMER_PROCESS_STATE_FOREGROUND_MS = 10041; // 0x2739
+    field public static final int TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS = 10039; // 0x2737
+    field public static final int TIMER_PROCESS_STATE_TOP_MS = 10038; // 0x2736
+    field public static final int TIMER_PROCESS_STATE_TOP_SLEEPING_MS = 10040; // 0x2738
+    field public static final int TIMER_VIBRATOR = 10044; // 0x273c
+    field public static final int TIMER_VIDEO = 10033; // 0x2731
+    field public static final int TIMER_WIFI_SCAN = 10030; // 0x272e
+  }
+
+}
+
 package android.os.storage {
 
   public abstract class OnObbStateChangeListener {
@@ -30570,6 +30747,7 @@
   public static class CallLog.Calls implements android.provider.BaseColumns {
     ctor public CallLog.Calls();
     method public static java.lang.String getLastOutgoingCall(android.content.Context);
+    field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7
     field public static final int BLOCKED_TYPE = 6; // 0x6
     field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number";
     field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri";
@@ -30592,6 +30770,7 @@
     field public static final java.lang.String DURATION = "duration";
     field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER";
     field public static final java.lang.String FEATURES = "features";
+    field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2
     field public static final int FEATURES_VIDEO = 1; // 0x1
     field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location";
     field public static final int INCOMING_TYPE = 1; // 0x1
@@ -32235,7 +32414,6 @@
     field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS";
     field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS";
     field public static final java.lang.String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
-    field public static final java.lang.String ACTION_SCREEN_READER_TUTORIAL = "android.settings.SCREEN_READER_TUTORIAL";
     field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
     field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS";
     field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";
@@ -35866,9 +36044,11 @@
     method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
+    method public void pullExternalCall();
     method public void registerCallback(android.telecom.Call.Callback);
     method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
     method public void reject(boolean, java.lang.String);
+    method public void sendCallEvent(java.lang.String, android.os.Bundle);
     method public void splitFromConference();
     method public void stopDtmfTone();
     method public void swapConference();
@@ -35882,6 +36062,7 @@
     field public static final int STATE_DISCONNECTING = 10; // 0xa
     field public static final int STATE_HOLDING = 3; // 0x3
     field public static final int STATE_NEW = 0; // 0x0
+    field public static final int STATE_PULLING_CALL = 11; // 0xb
     field public static final int STATE_RINGING = 2; // 0x2
     field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8
   }
@@ -35892,6 +36073,7 @@
     method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List<java.lang.String>);
     method public void onChildrenChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
     method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
+    method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
     method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
     method public void onParentChanged(android.telecom.Call, android.telecom.Call);
     method public void onPostDialWait(android.telecom.Call, java.lang.String);
@@ -35922,6 +36104,7 @@
     method public static java.lang.String propertiesToString(int);
     field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+    field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
@@ -35941,6 +36124,7 @@
     field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4
     field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
     field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
+    field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
     field public static final int PROPERTY_WIFI = 8; // 0x8
     field public static final int PROPERTY_WORK_CALL = 32; // 0x20
   }
@@ -36055,15 +36239,19 @@
     method public void onAnswer(int);
     method public void onAnswer();
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
+    method public void onCallEvent(java.lang.String, android.os.Bundle);
     method public void onDisconnect();
     method public void onHold();
     method public void onPlayDtmfTone(char);
     method public void onPostDialContinue(boolean);
+    method public void onPullExternalCall();
     method public void onReject();
+    method public void onReject(java.lang.String);
     method public void onSeparate();
     method public void onStateChanged(int);
     method public void onStopDtmfTone();
     method public void onUnhold();
+    method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
     method public final void setActive();
     method public final void setAddress(android.net.Uri, int);
     method public final void setAudioModeIsVoip(boolean);
@@ -36087,9 +36275,12 @@
     method public static java.lang.String stateToString(int);
     field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+    field public static final int CAPABILITY_CAN_PULL_CALL = 33554432; // 0x2000000
+    field public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 4194304; // 0x400000
     field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
+    field public static final int CAPABILITY_IS_EXTERNAL_CALL = 16777216; // 0x1000000
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
     field public static final int CAPABILITY_MERGE_CONFERENCE = 4; // 0x4
     field public static final int CAPABILITY_MUTE = 64; // 0x40
@@ -36103,6 +36294,7 @@
     field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
+    field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
     field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
     field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
     field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -36112,6 +36304,7 @@
     field public static final int STATE_HOLDING = 5; // 0x5
     field public static final int STATE_INITIALIZING = 0; // 0x0
     field public static final int STATE_NEW = 1; // 0x1
+    field public static final int STATE_PULLING_CALL = 7; // 0x7
     field public static final int STATE_RINGING = 2; // 0x2
   }
 
@@ -36189,7 +36382,9 @@
     method public java.lang.String getReason();
     method public int getTone();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ANSWERED_ELSEWHERE = 11; // 0xb
     field public static final int BUSY = 7; // 0x7
+    field public static final int CALL_PULLED = 12; // 0xc
     field public static final int CANCELED = 4; // 0x4
     field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa
     field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR;
@@ -36225,6 +36420,7 @@
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
     method public void onCallRemoved(android.telecom.Call);
     method public void onCanAddCallChanged(boolean);
+    method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
     method public void onSilenceRinger();
     method public final void setAudioRoute(int);
     method public final void setMuted(boolean);
@@ -36375,6 +36571,7 @@
     method public boolean isVoipAudioMode();
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
+    method public void pullExternalCall();
     method public void registerCallback(android.telecom.RemoteConnection.Callback);
     method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler);
     method public void reject();
@@ -36391,6 +36588,7 @@
     method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference);
     method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List<android.telecom.RemoteConnection>);
     method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int);
+    method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle);
     method public void onDestroyed(android.telecom.RemoteConnection);
     method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause);
     method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle);
@@ -36488,6 +36686,7 @@
     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 java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -36629,6 +36828,7 @@
     field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
     field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
     field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
+    field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
     field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
     field public static final java.lang.String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
     field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
@@ -42393,6 +42593,7 @@
     method public void onStartTemporaryDetach();
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
+    method public void onVisibilityAggregated(boolean);
     method protected void onVisibilityChanged(android.view.View, int);
     method public void onWindowFocusChanged(boolean);
     method public void onWindowSystemUiVisibilityChanged(int);
@@ -43489,7 +43690,7 @@
     method public abstract boolean onMenuOpened(int, android.view.Menu);
     method public abstract void onPanelClosed(int, android.view.Menu);
     method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
+    method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public abstract boolean onSearchRequested();
     method public abstract boolean onSearchRequested(android.view.SearchEvent);
     method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
@@ -50720,6 +50921,7 @@
   public abstract interface Iterable {
     method public default void forEach(java.util.function.Consumer<? super T>);
     method public abstract java.util.Iterator<T> iterator();
+    method public default java.util.Spliterator<T> spliterator();
   }
 
   public class LinkageError extends java.lang.Error {
@@ -57140,6 +57342,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class ArrayList extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
@@ -57150,7 +57353,9 @@
     method public void ensureCapacity(int);
     method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
+    method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public void trimToSize();
   }
 
@@ -57233,6 +57438,24 @@
     method public static int hashCode(float[]);
     method public static int hashCode(double[]);
     method public static int hashCode(java.lang.Object[]);
+    method public static void parallelSort(byte[]);
+    method public static void parallelSort(byte[], int, int);
+    method public static void parallelSort(char[]);
+    method public static void parallelSort(char[], int, int);
+    method public static void parallelSort(short[]);
+    method public static void parallelSort(short[], int, int);
+    method public static void parallelSort(int[]);
+    method public static void parallelSort(int[], int, int);
+    method public static void parallelSort(long[]);
+    method public static void parallelSort(long[], int, int);
+    method public static void parallelSort(float[]);
+    method public static void parallelSort(float[], int, int);
+    method public static void parallelSort(double[]);
+    method public static void parallelSort(double[], int, int);
+    method public static void parallelSort(T[]);
+    method public static void parallelSort(T[], int, int);
+    method public static void parallelSort(T[], java.util.Comparator<? super T>);
+    method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
     method public static void sort(int[]);
     method public static void sort(int[], int, int);
     method public static void sort(long[]);
@@ -57251,6 +57474,14 @@
     method public static void sort(java.lang.Object[], int, int);
     method public static void sort(T[], java.util.Comparator<? super T>);
     method public static void sort(T[], int, int, java.util.Comparator<? super T>);
+    method public static java.util.Spliterator<T> spliterator(T[]);
+    method public static java.util.Spliterator<T> spliterator(T[], int, int);
+    method public static java.util.Spliterator.OfInt spliterator(int[]);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int, int);
+    method public static java.util.Spliterator.OfLong spliterator(long[]);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int, int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[]);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
     method public static java.lang.String toString(long[]);
     method public static java.lang.String toString(int[]);
     method public static java.lang.String toString(short[]);
@@ -57412,6 +57643,7 @@
     method public abstract java.util.Iterator<E> iterator();
     method public abstract boolean remove(java.lang.Object);
     method public abstract boolean removeAll(java.util.Collection<?>);
+    method public default boolean removeIf(java.util.function.Predicate<? super E>);
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
     method public abstract java.lang.Object[] toArray();
@@ -57750,6 +57982,7 @@
     method public java.lang.Object clone();
     method public java.util.Iterator<E> iterator();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class Hashtable extends java.util.Dictionary implements java.lang.Cloneable java.util.Map java.io.Serializable {
@@ -57894,6 +58127,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public abstract interface List implements java.util.Collection {
@@ -58043,23 +58277,37 @@
 
   public abstract interface Map {
     method public abstract void clear();
+    method public default V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public default V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public default V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public abstract boolean containsKey(java.lang.Object);
     method public abstract boolean containsValue(java.lang.Object);
     method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public abstract boolean equals(java.lang.Object);
     method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public abstract V get(java.lang.Object);
+    method public default V getOrDefault(java.lang.Object, V);
     method public abstract int hashCode();
     method public abstract boolean isEmpty();
     method public abstract java.util.Set<K> keySet();
+    method public default V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public abstract V put(K, V);
     method public abstract void putAll(java.util.Map<? extends K, ? extends V>);
+    method public default V putIfAbsent(K, V);
     method public abstract V remove(java.lang.Object);
+    method public default boolean remove(java.lang.Object, java.lang.Object);
+    method public default boolean replace(K, V, V);
+    method public default V replace(K, V);
+    method public default void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public abstract int size();
     method public abstract java.util.Collection<V> values();
   }
 
   public static abstract interface Map.Entry {
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue();
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>);
     method public abstract boolean equals(java.lang.Object);
     method public abstract K getKey();
     method public abstract V getValue();
@@ -58238,6 +58486,7 @@
   public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
+    ctor public PriorityQueue(java.util.Comparator<? super E>);
     ctor public PriorityQueue(int, java.util.Comparator<? super E>);
     ctor public PriorityQueue(java.util.Collection<? extends E>);
     ctor public PriorityQueue(java.util.PriorityQueue<? extends E>);
@@ -58248,6 +58497,7 @@
     method public E peek();
     method public E poll();
     method public int size();
+    method public final java.util.Spliterator<E> spliterator();
   }
 
   public class Properties extends java.util.Hashtable {
@@ -58490,6 +58740,111 @@
     method public abstract java.util.SortedSet<E> tailSet(E);
   }
 
+  public abstract interface Spliterator {
+    method public abstract int characteristics();
+    method public abstract long estimateSize();
+    method public default void forEachRemaining(java.util.function.Consumer<? super T>);
+    method public default java.util.Comparator<? super T> getComparator();
+    method public default long getExactSizeIfKnown();
+    method public default boolean hasCharacteristics(int);
+    method public abstract boolean tryAdvance(java.util.function.Consumer<? super T>);
+    method public abstract java.util.Spliterator<T> trySplit();
+    field public static final int CONCURRENT = 4096; // 0x1000
+    field public static final int DISTINCT = 1; // 0x1
+    field public static final int IMMUTABLE = 1024; // 0x400
+    field public static final int NONNULL = 256; // 0x100
+    field public static final int ORDERED = 16; // 0x10
+    field public static final int SIZED = 64; // 0x40
+    field public static final int SORTED = 4; // 0x4
+    field public static final int SUBSIZED = 16384; // 0x4000
+  }
+
+  public static abstract interface Spliterator.OfDouble implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.DoubleConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+    method public abstract boolean tryAdvance(java.util.function.DoubleConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Double>);
+    method public abstract java.util.Spliterator.OfDouble trySplit();
+  }
+
+  public static abstract interface Spliterator.OfInt implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.IntConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+    method public abstract boolean tryAdvance(java.util.function.IntConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Integer>);
+    method public abstract java.util.Spliterator.OfInt trySplit();
+  }
+
+  public static abstract interface Spliterator.OfLong implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.LongConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+    method public abstract boolean tryAdvance(java.util.function.LongConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Long>);
+    method public abstract java.util.Spliterator.OfLong trySplit();
+  }
+
+  public static abstract interface Spliterator.OfPrimitive implements java.util.Spliterator {
+    method public default void forEachRemaining(T_CONS);
+    method public abstract boolean tryAdvance(T_CONS);
+    method public abstract T_SPLITR trySplit();
+  }
+
+  public final class Spliterators {
+    method public static java.util.Spliterator.OfDouble emptyDoubleSpliterator();
+    method public static java.util.Spliterator.OfInt emptyIntSpliterator();
+    method public static java.util.Spliterator.OfLong emptyLongSpliterator();
+    method public static java.util.Spliterator<T> emptySpliterator();
+    method public static java.util.Iterator<T> iterator(java.util.Spliterator<? extends T>);
+    method public static java.util.PrimitiveIterator.OfInt iterator(java.util.Spliterator.OfInt);
+    method public static java.util.PrimitiveIterator.OfLong iterator(java.util.Spliterator.OfLong);
+    method public static java.util.PrimitiveIterator.OfDouble iterator(java.util.Spliterator.OfDouble);
+    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int);
+    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int, int, int);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int, int, int);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int, int, int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int, int, int);
+    method public static java.util.Spliterator<T> spliterator(java.util.Collection<? extends T>, int);
+    method public static java.util.Spliterator<T> spliterator(java.util.Iterator<? extends T>, long, int);
+    method public static java.util.Spliterator.OfInt spliterator(java.util.PrimitiveIterator.OfInt, long, int);
+    method public static java.util.Spliterator.OfLong spliterator(java.util.PrimitiveIterator.OfLong, long, int);
+    method public static java.util.Spliterator.OfDouble spliterator(java.util.PrimitiveIterator.OfDouble, long, int);
+    method public static java.util.Spliterator<T> spliteratorUnknownSize(java.util.Iterator<? extends T>, int);
+    method public static java.util.Spliterator.OfInt spliteratorUnknownSize(java.util.PrimitiveIterator.OfInt, int);
+    method public static java.util.Spliterator.OfLong spliteratorUnknownSize(java.util.PrimitiveIterator.OfLong, int);
+    method public static java.util.Spliterator.OfDouble spliteratorUnknownSize(java.util.PrimitiveIterator.OfDouble, int);
+  }
+
+  public static abstract class Spliterators.AbstractDoubleSpliterator implements java.util.Spliterator.OfDouble {
+    ctor protected Spliterators.AbstractDoubleSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfDouble trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractIntSpliterator implements java.util.Spliterator.OfInt {
+    ctor protected Spliterators.AbstractIntSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfInt trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractLongSpliterator implements java.util.Spliterator.OfLong {
+    ctor protected Spliterators.AbstractLongSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfLong trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractSpliterator implements java.util.Spliterator {
+    ctor protected Spliterators.AbstractSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator<T> trySplit();
+  }
+
   public class Stack extends java.util.Vector {
     ctor public Stack();
     method public boolean empty();
@@ -58499,6 +58854,15 @@
     method public synchronized int search(java.lang.Object);
   }
 
+  public final class StringJoiner {
+    ctor public StringJoiner(java.lang.CharSequence);
+    ctor public StringJoiner(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence);
+    method public java.util.StringJoiner add(java.lang.CharSequence);
+    method public int length();
+    method public java.util.StringJoiner merge(java.util.StringJoiner);
+    method public java.util.StringJoiner setEmptyValue(java.lang.CharSequence);
+  }
+
   public class StringTokenizer implements java.util.Enumeration {
     ctor public StringTokenizer(java.lang.String, java.lang.String, boolean);
     ctor public StringTokenizer(java.lang.String, java.lang.String);
@@ -58620,6 +58984,7 @@
     method public E pollFirst();
     method public E pollLast();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
     method public java.util.SortedSet<E> subSet(E, E);
     method public java.util.NavigableSet<E> tailSet(E, boolean);
@@ -58673,9 +59038,11 @@
     method public synchronized void removeAllElements();
     method public synchronized boolean removeElement(java.lang.Object);
     method public synchronized void removeElementAt(int);
+    method public synchronized boolean removeIf(java.util.function.Predicate<? super E>);
     method public synchronized void setElementAt(E, int);
     method public synchronized void setSize(int);
     method public synchronized int size();
+    method public java.util.Spliterator<E> spliterator();
     method public synchronized void trimToSize();
     field protected int capacityIncrement;
     field protected int elementCount;
@@ -58723,6 +59090,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -58786,6 +59154,78 @@
     ctor public CancellationException(java.lang.String);
   }
 
+  public class CompletableFuture implements java.util.concurrent.CompletionStage java.util.concurrent.Future {
+    ctor public CompletableFuture();
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> allOf(java.util.concurrent.CompletableFuture<?>...);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Object> anyOf(java.util.concurrent.CompletableFuture<?>...);
+    method public java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public boolean cancel(boolean);
+    method public boolean complete(T);
+    method public boolean completeExceptionally(java.lang.Throwable);
+    method public static java.util.concurrent.CompletableFuture<U> completedFuture(U);
+    method public java.util.concurrent.CompletableFuture<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
+    method public T get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public T get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public T getNow(T);
+    method public int getNumberOfDependents();
+    method public java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public boolean isCancelled();
+    method public boolean isCompletedExceptionally();
+    method public boolean isDone();
+    method public T join();
+    method public void obtrudeException(java.lang.Throwable);
+    method public void obtrudeValue(T);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>);
+    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRun(java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<T> toCompletableFuture();
+    method public java.util.concurrent.CompletableFuture<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
+  }
+
+  public static abstract interface CompletableFuture.AsynchronousCompletionTask {
+  }
+
+  public class CompletionException extends java.lang.RuntimeException {
+    ctor protected CompletionException();
+    ctor protected CompletionException(java.lang.String);
+    ctor public CompletionException(java.lang.String, java.lang.Throwable);
+    ctor public CompletionException(java.lang.Throwable);
+  }
+
   public abstract interface CompletionService {
     method public abstract java.util.concurrent.Future<V> poll();
     method public abstract java.util.concurrent.Future<V> poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
@@ -58794,20 +59234,130 @@
     method public abstract java.util.concurrent.Future<V> take() throws java.lang.InterruptedException;
   }
 
+  public abstract interface CompletionStage {
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
+    method public abstract java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRun(java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletableFuture<T> toCompletableFuture();
+    method public abstract java.util.concurrent.CompletionStage<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
+  }
+
   public class ConcurrentHashMap extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable {
     ctor public ConcurrentHashMap();
     ctor public ConcurrentHashMap(int);
     ctor public ConcurrentHashMap(java.util.Map<? extends K, ? extends V>);
     ctor public ConcurrentHashMap(int, float);
     ctor public ConcurrentHashMap(int, float, int);
+    method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public boolean contains(java.lang.Object);
     method public java.util.Enumeration<V> elements();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public void forEach(long, java.util.function.BiConsumer<? super K, ? super V>);
+    method public void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachEntry(long, java.util.function.Consumer<? super java.util.Map.Entry<K, V>>);
+    method public void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachKey(long, java.util.function.Consumer<? super K>);
+    method public void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachValue(long, java.util.function.Consumer<? super V>);
+    method public void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public V getOrDefault(java.lang.Object, V);
+    method public java.util.concurrent.ConcurrentHashMap.KeySetView<K, V> keySet(V);
     method public java.util.Enumeration<K> keys();
+    method public long mappingCount();
+    method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
+    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet();
+    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int);
     method public V putIfAbsent(K, V);
+    method public U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public java.util.Map.Entry<K, V> reduceEntries(long, java.util.function.BiFunction<java.util.Map.Entry<K, V>, java.util.Map.Entry<K, V>, ? extends java.util.Map.Entry<K, V>>);
+    method public U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceEntriesToDouble(long, java.util.function.ToDoubleFunction<java.util.Map.Entry<K, V>>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceEntriesToInt(long, java.util.function.ToIntFunction<java.util.Map.Entry<K, V>>, int, java.util.function.IntBinaryOperator);
+    method public long reduceEntriesToLong(long, java.util.function.ToLongFunction<java.util.Map.Entry<K, V>>, long, java.util.function.LongBinaryOperator);
+    method public K reduceKeys(long, java.util.function.BiFunction<? super K, ? super K, ? extends K>);
+    method public U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceKeysToDouble(long, java.util.function.ToDoubleFunction<? super K>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceKeysToInt(long, java.util.function.ToIntFunction<? super K>, int, java.util.function.IntBinaryOperator);
+    method public long reduceKeysToLong(long, java.util.function.ToLongFunction<? super K>, long, java.util.function.LongBinaryOperator);
+    method public double reduceToDouble(long, java.util.function.ToDoubleBiFunction<? super K, ? super V>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceToInt(long, java.util.function.ToIntBiFunction<? super K, ? super V>, int, java.util.function.IntBinaryOperator);
+    method public long reduceToLong(long, java.util.function.ToLongBiFunction<? super K, ? super V>, long, java.util.function.LongBinaryOperator);
+    method public V reduceValues(long, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
+    method public U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceValuesToDouble(long, java.util.function.ToDoubleFunction<? super V>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceValuesToInt(long, java.util.function.ToIntFunction<? super V>, int, java.util.function.IntBinaryOperator);
+    method public long reduceValuesToLong(long, java.util.function.ToLongFunction<? super V>, long, java.util.function.LongBinaryOperator);
     method public boolean remove(java.lang.Object, java.lang.Object);
     method public boolean replace(K, V, V);
     method public V replace(K, V);
+    method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>);
+    method public U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>);
+    method public U searchKeys(long, java.util.function.Function<? super K, ? extends U>);
+    method public U searchValues(long, java.util.function.Function<? super V, ? extends U>);
+  }
+
+   static abstract class ConcurrentHashMap.CollectionView implements java.util.Collection java.io.Serializable {
+    method public final void clear();
+    method public abstract boolean contains(java.lang.Object);
+    method public final boolean containsAll(java.util.Collection<?>);
+    method public java.util.concurrent.ConcurrentHashMap<K, V> getMap();
+    method public final boolean isEmpty();
+    method public abstract java.util.Iterator<E> iterator();
+    method public abstract boolean remove(java.lang.Object);
+    method public final boolean removeAll(java.util.Collection<?>);
+    method public final boolean retainAll(java.util.Collection<?>);
+    method public final int size();
+    method public final java.lang.Object[] toArray();
+    method public final T[] toArray(T[]);
+    method public final java.lang.String toString();
+  }
+
+  public static class ConcurrentHashMap.KeySetView extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set {
+    method public boolean add(K);
+    method public boolean addAll(java.util.Collection<? extends K>);
+    method public boolean contains(java.lang.Object);
+    method public void forEach(java.util.function.Consumer<? super K>);
+    method public V getMappedValue();
+    method public java.util.Iterator<K> iterator();
+    method public boolean remove(java.lang.Object);
+    method public java.util.Spliterator<K> spliterator();
   }
 
   public class ConcurrentLinkedDeque extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable {
@@ -58837,6 +59387,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable {
@@ -58847,6 +59398,7 @@
     method public E peek();
     method public E poll();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public abstract interface ConcurrentMap implements java.util.Map {
@@ -58878,6 +59430,9 @@
     method public K ceilingKey(K);
     method public java.util.concurrent.ConcurrentSkipListMap<K, V> clone();
     method public java.util.Comparator<? super K> comparator();
+    method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public java.util.NavigableSet<K> descendingKeySet();
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> descendingMap();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
@@ -58885,6 +59440,8 @@
     method public K firstKey();
     method public java.util.Map.Entry<K, V> floorEntry(K);
     method public K floorKey(K);
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public V getOrDefault(java.lang.Object, V);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K, boolean);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K);
     method public java.util.Map.Entry<K, V> higherEntry(K);
@@ -58893,6 +59450,7 @@
     method public K lastKey();
     method public java.util.Map.Entry<K, V> lowerEntry(K);
     method public K lowerKey(K);
+    method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public java.util.NavigableSet<K> navigableKeySet();
     method public java.util.Map.Entry<K, V> pollFirstEntry();
     method public java.util.Map.Entry<K, V> pollLastEntry();
@@ -58900,6 +59458,7 @@
     method public boolean remove(java.lang.Object, java.lang.Object);
     method public boolean replace(K, V, V);
     method public V replace(K, V);
+    method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, boolean, K, boolean);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, K);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K, boolean);
@@ -58927,6 +59486,7 @@
     method public E pollFirst();
     method public E pollLast();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
     method public java.util.NavigableSet<E> subSet(E, E);
     method public java.util.NavigableSet<E> tailSet(E, boolean);
@@ -58970,8 +59530,11 @@
   public class CopyOnWriteArraySet extends java.util.AbstractSet implements java.io.Serializable {
     ctor public CopyOnWriteArraySet();
     ctor public CopyOnWriteArraySet(java.util.Collection<? extends E>);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public java.util.Iterator<E> iterator();
+    method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class CountDownLatch {
@@ -58982,6 +59545,32 @@
     method public long getCount();
   }
 
+  public abstract class CountedCompleter extends java.util.concurrent.ForkJoinTask {
+    ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>, int);
+    ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>);
+    ctor protected CountedCompleter();
+    method public final void addToPendingCount(int);
+    method public final boolean compareAndSetPendingCount(int, int);
+    method public void complete(T);
+    method public abstract void compute();
+    method public final int decrementPendingCountUnlessZero();
+    method protected final boolean exec();
+    method public final java.util.concurrent.CountedCompleter<?> firstComplete();
+    method public final java.util.concurrent.CountedCompleter<?> getCompleter();
+    method public final int getPendingCount();
+    method public T getRawResult();
+    method public final java.util.concurrent.CountedCompleter<?> getRoot();
+    method public final void helpComplete(int);
+    method public final java.util.concurrent.CountedCompleter<?> nextComplete();
+    method public void onCompletion(java.util.concurrent.CountedCompleter<?>);
+    method public boolean onExceptionalCompletion(java.lang.Throwable, java.util.concurrent.CountedCompleter<?>);
+    method public final void propagateCompletion();
+    method public final void quietlyCompleteRoot();
+    method public final void setPendingCount(int);
+    method protected void setRawResult(T);
+    method public final void tryComplete();
+  }
+
   public class CyclicBarrier {
     ctor public CyclicBarrier(int, java.lang.Runnable);
     ctor public CyclicBarrier(int);
@@ -59072,6 +59661,8 @@
     method public static java.util.concurrent.ExecutorService newSingleThreadExecutor(java.util.concurrent.ThreadFactory);
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor();
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory);
+    method public static java.util.concurrent.ExecutorService newWorkStealingPool(int);
+    method public static java.util.concurrent.ExecutorService newWorkStealingPool();
     method public static java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.ThreadFactory privilegedThreadFactory();
@@ -59085,11 +59676,13 @@
     ctor public ForkJoinPool(int, java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory, java.lang.Thread.UncaughtExceptionHandler, boolean);
     method public boolean awaitQuiescence(long, java.util.concurrent.TimeUnit);
     method public boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public static java.util.concurrent.ForkJoinPool commonPool();
     method protected int drainTasksTo(java.util.Collection<? super java.util.concurrent.ForkJoinTask<?>>);
     method public void execute(java.util.concurrent.ForkJoinTask<?>);
     method public void execute(java.lang.Runnable);
     method public int getActiveThreadCount();
     method public boolean getAsyncMode();
+    method public static int getCommonPoolParallelism();
     method public java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory getFactory();
     method public int getParallelism();
     method public int getPoolSize();
@@ -59127,6 +59720,7 @@
     method public static java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T);
     method public static java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>);
     method public boolean cancel(boolean);
+    method public final boolean compareAndSetForkJoinTaskTag(short, short);
     method public void complete(V);
     method public void completeExceptionally(java.lang.Throwable);
     method protected abstract boolean exec();
@@ -59134,6 +59728,7 @@
     method public final V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
     method public final V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
     method public final java.lang.Throwable getException();
+    method public final short getForkJoinTaskTag();
     method public static java.util.concurrent.ForkJoinPool getPool();
     method public static int getQueuedTaskCount();
     method public abstract V getRawResult();
@@ -59152,9 +59747,11 @@
     method protected static java.util.concurrent.ForkJoinTask<?> peekNextLocalTask();
     method protected static java.util.concurrent.ForkJoinTask<?> pollNextLocalTask();
     method protected static java.util.concurrent.ForkJoinTask<?> pollTask();
+    method public final void quietlyComplete();
     method public final void quietlyInvoke();
     method public final void quietlyJoin();
     method public void reinitialize();
+    method public final short setForkJoinTaskTag(short);
     method protected abstract void setRawResult(V);
     method public boolean tryUnfork();
   }
@@ -59228,6 +59825,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
     method public E takeFirst() throws java.lang.InterruptedException;
     method public E takeLast() throws java.lang.InterruptedException;
@@ -59248,6 +59846,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -59267,6 +59866,7 @@
     method public void put(E);
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
     method public void transfer(E) throws java.lang.InterruptedException;
     method public boolean tryTransfer(E);
@@ -59314,6 +59914,7 @@
     method public void put(E);
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -59417,6 +60018,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -59546,112 +60148,136 @@
   public class AtomicInteger extends java.lang.Number implements java.io.Serializable {
     ctor public AtomicInteger(int);
     ctor public AtomicInteger();
+    method public final int accumulateAndGet(int, java.util.function.IntBinaryOperator);
     method public final int addAndGet(int);
     method public final boolean compareAndSet(int, int);
     method public final int decrementAndGet();
     method public double doubleValue();
     method public float floatValue();
     method public final int get();
+    method public final int getAndAccumulate(int, java.util.function.IntBinaryOperator);
     method public final int getAndAdd(int);
     method public final int getAndDecrement();
     method public final int getAndIncrement();
     method public final int getAndSet(int);
+    method public final int getAndUpdate(java.util.function.IntUnaryOperator);
     method public final int incrementAndGet();
     method public int intValue();
     method public final void lazySet(int);
     method public long longValue();
     method public final void set(int);
+    method public final int updateAndGet(java.util.function.IntUnaryOperator);
     method public final boolean weakCompareAndSet(int, int);
   }
 
   public class AtomicIntegerArray implements java.io.Serializable {
     ctor public AtomicIntegerArray(int);
     ctor public AtomicIntegerArray(int[]);
+    method public final int accumulateAndGet(int, int, java.util.function.IntBinaryOperator);
     method public final int addAndGet(int, int);
     method public final boolean compareAndSet(int, int, int);
     method public final int decrementAndGet(int);
     method public final int get(int);
+    method public final int getAndAccumulate(int, int, java.util.function.IntBinaryOperator);
     method public final int getAndAdd(int, int);
     method public final int getAndDecrement(int);
     method public final int getAndIncrement(int);
     method public final int getAndSet(int, int);
+    method public final int getAndUpdate(int, java.util.function.IntUnaryOperator);
     method public final int incrementAndGet(int);
     method public final void lazySet(int, int);
     method public final int length();
     method public final void set(int, int);
+    method public final int updateAndGet(int, java.util.function.IntUnaryOperator);
     method public final boolean weakCompareAndSet(int, int, int);
   }
 
   public abstract class AtomicIntegerFieldUpdater {
     ctor protected AtomicIntegerFieldUpdater();
+    method public final int accumulateAndGet(T, int, java.util.function.IntBinaryOperator);
     method public int addAndGet(T, int);
     method public abstract boolean compareAndSet(T, int, int);
     method public int decrementAndGet(T);
     method public abstract int get(T);
+    method public final int getAndAccumulate(T, int, java.util.function.IntBinaryOperator);
     method public int getAndAdd(T, int);
     method public int getAndDecrement(T);
     method public int getAndIncrement(T);
     method public int getAndSet(T, int);
+    method public final int getAndUpdate(T, java.util.function.IntUnaryOperator);
     method public int incrementAndGet(T);
     method public abstract void lazySet(T, int);
     method public static java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, int);
+    method public final int updateAndGet(T, java.util.function.IntUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, int, int);
   }
 
   public class AtomicLong extends java.lang.Number implements java.io.Serializable {
     ctor public AtomicLong(long);
     ctor public AtomicLong();
+    method public final long accumulateAndGet(long, java.util.function.LongBinaryOperator);
     method public final long addAndGet(long);
     method public final boolean compareAndSet(long, long);
     method public final long decrementAndGet();
     method public double doubleValue();
     method public float floatValue();
     method public final long get();
+    method public final long getAndAccumulate(long, java.util.function.LongBinaryOperator);
     method public final long getAndAdd(long);
     method public final long getAndDecrement();
     method public final long getAndIncrement();
     method public final long getAndSet(long);
+    method public final long getAndUpdate(java.util.function.LongUnaryOperator);
     method public final long incrementAndGet();
     method public int intValue();
     method public final void lazySet(long);
     method public long longValue();
     method public final void set(long);
+    method public final long updateAndGet(java.util.function.LongUnaryOperator);
     method public final boolean weakCompareAndSet(long, long);
   }
 
   public class AtomicLongArray implements java.io.Serializable {
     ctor public AtomicLongArray(int);
     ctor public AtomicLongArray(long[]);
+    method public final long accumulateAndGet(int, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(int, long);
     method public final boolean compareAndSet(int, long, long);
     method public final long decrementAndGet(int);
     method public final long get(int);
+    method public final long getAndAccumulate(int, long, java.util.function.LongBinaryOperator);
     method public final long getAndAdd(int, long);
     method public final long getAndDecrement(int);
     method public final long getAndIncrement(int);
     method public final long getAndSet(int, long);
+    method public final long getAndUpdate(int, java.util.function.LongUnaryOperator);
     method public final long incrementAndGet(int);
     method public final void lazySet(int, long);
     method public final int length();
     method public final void set(int, long);
+    method public final long updateAndGet(int, java.util.function.LongUnaryOperator);
     method public final boolean weakCompareAndSet(int, long, long);
   }
 
   public abstract class AtomicLongFieldUpdater {
     ctor protected AtomicLongFieldUpdater();
+    method public final long accumulateAndGet(T, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(T, long);
     method public abstract boolean compareAndSet(T, long, long);
     method public long decrementAndGet(T);
     method public abstract long get(T);
+    method public final long getAndAccumulate(T, long, java.util.function.LongBinaryOperator);
     method public long getAndAdd(T, long);
     method public long getAndDecrement(T);
     method public long getAndIncrement(T);
     method public long getAndSet(T, long);
+    method public final long getAndUpdate(T, java.util.function.LongUnaryOperator);
     method public long incrementAndGet(T);
     method public abstract void lazySet(T, long);
     method public static java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, long);
+    method public final long updateAndGet(T, java.util.function.LongUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, long, long);
   }
 
@@ -59669,34 +60295,46 @@
   public class AtomicReference implements java.io.Serializable {
     ctor public AtomicReference(V);
     ctor public AtomicReference();
+    method public final V accumulateAndGet(V, java.util.function.BinaryOperator<V>);
     method public final boolean compareAndSet(V, V);
     method public final V get();
+    method public final V getAndAccumulate(V, java.util.function.BinaryOperator<V>);
     method public final V getAndSet(V);
+    method public final V getAndUpdate(java.util.function.UnaryOperator<V>);
     method public final void lazySet(V);
     method public final void set(V);
+    method public final V updateAndGet(java.util.function.UnaryOperator<V>);
     method public final boolean weakCompareAndSet(V, V);
   }
 
   public class AtomicReferenceArray implements java.io.Serializable {
     ctor public AtomicReferenceArray(int);
     ctor public AtomicReferenceArray(E[]);
+    method public final E accumulateAndGet(int, E, java.util.function.BinaryOperator<E>);
     method public final boolean compareAndSet(int, E, E);
     method public final E get(int);
+    method public final E getAndAccumulate(int, E, java.util.function.BinaryOperator<E>);
     method public final E getAndSet(int, E);
+    method public final E getAndUpdate(int, java.util.function.UnaryOperator<E>);
     method public final void lazySet(int, E);
     method public final int length();
     method public final void set(int, E);
+    method public final E updateAndGet(int, java.util.function.UnaryOperator<E>);
     method public final boolean weakCompareAndSet(int, E, E);
   }
 
   public abstract class AtomicReferenceFieldUpdater {
     ctor protected AtomicReferenceFieldUpdater();
+    method public final V accumulateAndGet(T, V, java.util.function.BinaryOperator<V>);
     method public abstract boolean compareAndSet(T, V, V);
     method public abstract V get(T);
+    method public final V getAndAccumulate(T, V, java.util.function.BinaryOperator<V>);
     method public V getAndSet(T, V);
+    method public final V getAndUpdate(T, java.util.function.UnaryOperator<V>);
     method public abstract void lazySet(T, V);
     method public static java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String);
     method public abstract void set(T, V);
+    method public final V updateAndGet(T, java.util.function.UnaryOperator<V>);
     method public abstract boolean weakCompareAndSet(T, V, V);
   }
 
@@ -59711,6 +60349,59 @@
     method public boolean weakCompareAndSet(V, V, int, int);
   }
 
+  public class DoubleAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public DoubleAccumulator(java.util.function.DoubleBinaryOperator, double);
+    method public void accumulate(double);
+    method public double doubleValue();
+    method public float floatValue();
+    method public double get();
+    method public double getThenReset();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+  }
+
+  public class DoubleAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public DoubleAdder();
+    method public void add(double);
+    method public double doubleValue();
+    method public float floatValue();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+    method public double sum();
+    method public double sumThenReset();
+  }
+
+  public class LongAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public LongAccumulator(java.util.function.LongBinaryOperator, long);
+    method public void accumulate(long);
+    method public double doubleValue();
+    method public float floatValue();
+    method public long get();
+    method public long getThenReset();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+  }
+
+  public class LongAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public LongAdder();
+    method public void add(long);
+    method public void decrement();
+    method public double doubleValue();
+    method public float floatValue();
+    method public void increment();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+    method public long sum();
+    method public long sumThenReset();
+  }
+
+   abstract class Striped64 extends java.lang.Number {
+  }
+
 }
 
 package java.util.concurrent.locks {
@@ -59918,6 +60609,34 @@
     method public void unlock();
   }
 
+  public class StampedLock implements java.io.Serializable {
+    ctor public StampedLock();
+    method public java.util.concurrent.locks.Lock asReadLock();
+    method public java.util.concurrent.locks.ReadWriteLock asReadWriteLock();
+    method public java.util.concurrent.locks.Lock asWriteLock();
+    method public int getReadLockCount();
+    method public boolean isReadLocked();
+    method public boolean isWriteLocked();
+    method public long readLock();
+    method public long readLockInterruptibly() throws java.lang.InterruptedException;
+    method public long tryConvertToOptimisticRead(long);
+    method public long tryConvertToReadLock(long);
+    method public long tryConvertToWriteLock(long);
+    method public long tryOptimisticRead();
+    method public long tryReadLock();
+    method public long tryReadLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public boolean tryUnlockRead();
+    method public boolean tryUnlockWrite();
+    method public long tryWriteLock();
+    method public long tryWriteLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public void unlock(long);
+    method public void unlockRead(long);
+    method public void unlockWrite(long);
+    method public boolean validate(long);
+    method public long writeLock();
+    method public long writeLockInterruptibly() throws java.lang.InterruptedException;
+  }
+
 }
 
 package java.util.function {
diff --git a/api/removed.txt b/api/removed.txt
index 2f55373..8ac2d63 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -35,6 +35,25 @@
 
 }
 
+package android.graphics {
+
+  public deprecated class AvoidXfermode extends android.graphics.Xfermode {
+    ctor public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode);
+  }
+
+  public static final class AvoidXfermode.Mode extends java.lang.Enum {
+    method public static android.graphics.AvoidXfermode.Mode valueOf(java.lang.String);
+    method public static final android.graphics.AvoidXfermode.Mode[] values();
+    enum_constant public static final android.graphics.AvoidXfermode.Mode AVOID;
+    enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET;
+  }
+
+  public deprecated class PixelXorXfermode extends android.graphics.Xfermode {
+    ctor public PixelXorXfermode(int);
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 75a0e4d..73464d3f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -654,6 +654,7 @@
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillColor = 16843780; // 0x1010404
     field public static final int fillEnabled = 16843343; // 0x101024f
+    field public static final int fillType = 16844064; // 0x1010520
     field public static final int fillViewport = 16843130; // 0x101017a
     field public static final int filter = 16843035; // 0x101011b
     field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -974,6 +975,7 @@
     field public static final int nextFocusLeft = 16842977; // 0x10100e1
     field public static final int nextFocusRight = 16842978; // 0x10100e2
     field public static final int nextFocusUp = 16842979; // 0x10100e3
+    field public static final int nfcAntennaPositionDrawable = 16844063; // 0x101051f
     field public static final int noHistory = 16843309; // 0x101022d
     field public static final int normalScreens = 16843397; // 0x1010285
     field public static final int notificationTimeout = 16843651; // 0x1010383
@@ -3556,7 +3558,7 @@
     method public android.view.View getCurrentFocus();
     method public android.app.FragmentManager getFragmentManager();
     method public android.content.Intent getIntent();
-    method public deprecated java.lang.Object getLastNonConfigurationInstance();
+    method public java.lang.Object getLastNonConfigurationInstance();
     method public android.view.LayoutInflater getLayoutInflater();
     method public android.app.LoaderManager getLoaderManager();
     method public java.lang.String getLocalClassName();
@@ -3652,14 +3654,13 @@
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public void onProvideAssistContent(android.app.assist.AssistContent);
     method public void onProvideAssistData(android.os.Bundle);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public android.net.Uri onProvideReferrer();
     method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
     method protected void onRestart();
     method protected void onRestoreInstanceState(android.os.Bundle);
     method public void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method protected void onResume();
-    method public deprecated java.lang.Object onRetainNonConfigurationInstance();
+    method public java.lang.Object onRetainNonConfigurationInstance();
     method protected void onSaveInstanceState(android.os.Bundle);
     method public void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -4349,7 +4350,6 @@
     method public void onPanelClosed(int, android.view.Menu);
     method public boolean onPrepareOptionsMenu(android.view.Menu);
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public void onRestoreInstanceState(android.os.Bundle);
     method public android.os.Bundle onSaveInstanceState();
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -5990,7 +5990,6 @@
     method public int getCurrentFailedPasswordAttempts();
     method public deprecated java.lang.String getDeviceInitializerApp();
     method public deprecated android.content.ComponentName getDeviceInitializerComponent();
-    method public boolean getDeviceLoggingEnabled(android.content.ComponentName);
     method public java.lang.String getDeviceOwner();
     method public java.lang.String getDeviceOwnerLockScreenInfo();
     method public java.lang.String getDeviceOwnerNameOnAnyUser();
@@ -6046,6 +6045,7 @@
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isProfileOwnerApp(java.lang.String);
     method public boolean isProvisioningAllowed(java.lang.String);
+    method public boolean isSecurityLoggingEnabled(android.content.ComponentName);
     method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String);
     method public void lockNow();
     method public void notifyPendingSystemUpdate(long);
@@ -6056,8 +6056,8 @@
     method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
     method public boolean requestBugreport(android.content.ComponentName);
     method public boolean resetPassword(java.lang.String, int);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrieveDeviceLogs(android.content.ComponentName);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrievePreviousDeviceLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
     method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
     method public deprecated boolean setActiveProfileOwner(android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException;
     method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
@@ -6070,7 +6070,6 @@
     method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
     method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
     method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean);
-    method public void setDeviceLoggingEnabled(android.content.ComponentName, boolean);
     method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String);
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
@@ -6103,6 +6102,7 @@
     method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
     method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+    method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean);
     method public void setShortSupportMessage(android.content.ComponentName, java.lang.String);
     method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
@@ -6129,6 +6129,7 @@
     field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
     field public static final int ENCRYPTION_STATUS_ACTIVE = 3; // 0x3
     field public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4; // 0x4
+    field public static final int ENCRYPTION_STATUS_ACTIVE_PER_USER = 5; // 0x5
     field public static final int ENCRYPTION_STATUS_INACTIVE = 1; // 0x1
     field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0
     field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
@@ -6196,6 +6197,27 @@
     field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
   }
 
+  public class SecurityLog {
+    ctor public SecurityLog();
+    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
+    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
+    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
+    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
+    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
+    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
+    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
+  }
+
+  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.Object getData();
+    method public int getTag();
+    method public long getTimeNanos();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.admin.SecurityLog.SecurityEvent> CREATOR;
+  }
+
   public class SystemUpdatePolicy implements android.os.Parcelable {
     method public static android.app.admin.SystemUpdatePolicy createAutomaticInstallPolicy();
     method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy();
@@ -6637,8 +6659,8 @@
     method public long getTxPackets();
     method public int getUid();
     field public static final int ROAMING_ALL = -1; // 0xffffffff
-    field public static final int ROAMING_DEFAULT = 1; // 0x1
-    field public static final int ROAMING_ROAMING = 2; // 0x2
+    field public static final int ROAMING_NO = 1; // 0x1
+    field public static final int ROAMING_YES = 2; // 0x2
     field public static final int STATE_ALL = -1; // 0xffffffff
     field public static final int STATE_DEFAULT = 1; // 0x1
     field public static final int STATE_FOREGROUND = 2; // 0x2
@@ -6846,31 +6868,6 @@
 
 }
 
-package android.auditing {
-
-  public class SecurityLog {
-    ctor public SecurityLog();
-    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
-    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
-    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
-    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
-    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
-    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
-    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
-    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
-  }
-
-  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public java.lang.Object getData();
-    method public int getTag();
-    method public long getTimeNanos();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.auditing.SecurityLog.SecurityEvent> CREATOR;
-  }
-
-}
-
 package android.bluetooth {
 
   public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
@@ -8407,6 +8404,7 @@
     field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
     field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
     field public static final java.lang.String CONSUMER_IR_SERVICE = "consumer_ir";
+    field public static final java.lang.String CONTEXTHUB_SERVICE = "contexthub";
     field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
     field public static final int CONTEXT_INCLUDE_CODE = 1; // 0x1
     field public static final int CONTEXT_RESTRICTED = 4; // 0x4
@@ -8415,7 +8413,7 @@
     field public static final java.lang.String DOWNLOAD_SERVICE = "download";
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
     field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
-    field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardwareproperties";
+    field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
     field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
     field public static final java.lang.String INPUT_SERVICE = "input";
@@ -8448,6 +8446,7 @@
     field public static final java.lang.String SENSOR_SERVICE = "sensor";
     field public static final java.lang.String SHORTCUT_SERVICE = "shortcut";
     field public static final java.lang.String STORAGE_SERVICE = "storage";
+    field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth";
     field public static final java.lang.String TELECOM_SERVICE = "telecom";
     field public static final java.lang.String TELEPHONY_SERVICE = "phone";
     field public static final java.lang.String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
@@ -9647,6 +9646,7 @@
     field public int flags;
     field public int largestWidthLimitDp;
     field public java.lang.String manageSpaceActivityName;
+    field public java.lang.String minSdkVersion;
     field public java.lang.String nativeLibraryDir;
     field public java.lang.String permission;
     field public java.lang.String processName;
@@ -9784,6 +9784,7 @@
     method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
+    method public boolean hasShortcutHostPermission();
     method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
     method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
     method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
@@ -9894,6 +9895,7 @@
     method public java.lang.String[] getNames() throws java.io.IOException;
     method public java.io.InputStream openRead(java.lang.String) throws java.io.IOException;
     method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
+    method public void removeSplit(java.lang.String) throws java.io.IOException;
     method public void setStagingProgress(float);
   }
 
@@ -9923,6 +9925,7 @@
   public static class PackageInstaller.SessionParams implements android.os.Parcelable {
     ctor public PackageInstaller.SessionParams(int);
     method public int describeContents();
+    method public void setAllowDowngrade(boolean);
     method public void setAppIcon(android.graphics.Bitmap);
     method public void setAppLabel(java.lang.CharSequence);
     method public void setAppPackageName(java.lang.String);
@@ -10388,6 +10391,7 @@
     method public int getWeight();
     method public boolean hasIconFile();
     method public boolean hasIconResource();
+    method public boolean hasKeyFieldsOnly();
     method public boolean isDynamic();
     method public boolean isPinned();
     method public void writeToParcel(android.os.Parcel, int);
@@ -10398,6 +10402,7 @@
     field public static final int FLAG_DYNAMIC = 1; // 0x1
     field public static final int FLAG_HAS_ICON_FILE = 8; // 0x8
     field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
+    field public static final int FLAG_KEY_FIELDS_ONLY = 16; // 0x10
     field public static final int FLAG_PINNED = 2; // 0x2
   }
 
@@ -10418,6 +10423,7 @@
     method public void deleteAllDynamicShortcuts();
     method public void deleteDynamicShortcut(java.lang.String);
     method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
+    method public int getIconMaxDimensions();
     method public int getMaxDynamicShortcutCount();
     method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
     method public long getRateLimitResetTime();
@@ -10502,7 +10508,6 @@
     method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
-    method public int getChangingConfigurations();
     method public int getColorForState(int[], int);
     method public int getDefaultColor();
     method public boolean isOpaque();
@@ -10514,6 +10519,7 @@
 
   public abstract class ComplexColor {
     ctor public ComplexColor();
+    method public int getChangingConfigurations();
     method public abstract int getDefaultColor();
     method public boolean isStateful();
   }
@@ -11861,17 +11867,6 @@
 
 package android.graphics {
 
-  public deprecated class AvoidXfermode extends android.graphics.Xfermode {
-    ctor public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode);
-  }
-
-  public static final class AvoidXfermode.Mode extends java.lang.Enum {
-    method public static android.graphics.AvoidXfermode.Mode valueOf(java.lang.String);
-    method public static final android.graphics.AvoidXfermode.Mode[] values();
-    enum_constant public static final android.graphics.AvoidXfermode.Mode AVOID;
-    enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET;
-  }
-
   public final class Bitmap implements android.os.Parcelable {
     method public boolean compress(android.graphics.Bitmap.CompressFormat, int, java.io.OutputStream);
     method public android.graphics.Bitmap copy(android.graphics.Bitmap.Config, boolean);
@@ -12738,10 +12733,6 @@
     field public int bytesPerPixel;
   }
 
-  public deprecated class PixelXorXfermode extends android.graphics.Xfermode {
-    ctor public PixelXorXfermode(int);
-  }
-
   public class Point implements android.os.Parcelable {
     ctor public Point();
     ctor public Point(int, int);
@@ -13301,7 +13292,8 @@
     method public int getGradientType();
     method public int getOpacity();
     method public android.graphics.drawable.GradientDrawable.Orientation getOrientation();
-    method public boolean isUseLevel();
+    method public int getShape();
+    method public boolean getUseLevel();
     method public void setAlpha(int);
     method public void setColor(int);
     method public void setColor(android.content.res.ColorStateList);
@@ -13420,9 +13412,9 @@
     method public void setPaddingMode(int);
     method public void setPaddingRelative(int, int, int, int);
     method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+    field public static final int INSET_UNDEFINED = -2147483648; // 0x80000000
     field public static final int PADDING_MODE_NEST = 0; // 0x0
     field public static final int PADDING_MODE_STACK = 1; // 0x1
-    field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000
   }
 
   public class LevelListDrawable extends android.graphics.drawable.DrawableContainer {
@@ -14170,6 +14162,7 @@
 
   public static abstract class CameraCaptureSession.CaptureCallback {
     ctor public CameraCaptureSession.CaptureCallback();
+    method public void onCaptureBufferLost(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.view.Surface, long);
     method public void onCaptureCompleted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult);
     method public void onCaptureFailed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureFailure);
     method public void onCaptureProgressed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
@@ -15280,37 +15273,32 @@
     method public java.lang.String getToolchain();
     method public int getToolchainVersion();
     method public java.lang.String getVendor();
-    method public void setId(int);
-    method public void setMemoryRegions(android.hardware.location.MemoryRegion[]);
-    method public void setName(java.lang.String);
-    method public void setPeakMips(float);
-    method public void setPeakPowerDrawMw(float);
-    method public void setPlatformVersion(int);
-    method public void setSleepPowerDrawMw(float);
-    method public void setStaticSwVersion(int);
-    method public void setStoppedPowerDrawMw(float);
-    method public void setSupportedSensors(int[]);
-    method public void setToolchain(java.lang.String);
-    method public void setToolchainVersion(int);
-    method public void setVendor(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.hardware.location.ContextHubInfo> CREATOR;
   }
 
   public final class ContextHubManager {
-    method public java.lang.Integer[] findNanoAppOnHub(int, android.hardware.location.NanoAppFilter);
-    method public int[] getContexthubHandles();
-    method public android.hardware.location.ContextHubInfo getContexthubInfo(int);
+    method public int[] findNanoAppOnHub(int, android.hardware.location.NanoAppFilter);
+    method public int[] getContextHubHandles();
+    method public android.hardware.location.ContextHubInfo getContextHubInfo(int);
     method public android.hardware.location.NanoAppInstanceInfo getNanoAppInstanceInfo(int);
     method public int loadNanoApp(int, android.hardware.location.NanoApp);
+    method public int registerContextHubCallback(android.hardware.location.ContextHubManager.ContextHubCallback);
+    method public int registerContextHubCallback(android.hardware.location.ContextHubManager.ContextHubCallback, android.os.Handler);
     method public int sendMessage(int, int, android.hardware.location.ContextHubMessage);
     method public int unloadNanoApp(int);
+    method public int unregisterContextHubCallback(android.hardware.location.ContextHubManager.ContextHubCallback);
     field public static final int ANY_HUB = -1; // 0xffffffff
     field public static final int MSG_DATA_SEND = 3; // 0x3
     field public static final int MSG_LOAD_NANO_APP = 1; // 0x1
     field public static final int MSG_UNLOAD_NANO_APP = 2; // 0x2
   }
 
+  public static abstract class ContextHubManager.ContextHubCallback {
+    ctor protected ContextHubManager.ContextHubCallback();
+    method public abstract void onMessageReceipt(int, int, android.hardware.location.ContextHubMessage);
+  }
+
   public class ContextHubMessage {
     ctor public ContextHubMessage(int, int, byte[]);
     method public int describeContents();
@@ -20415,24 +20403,6 @@
     method public boolean hasFullBiasNanos();
     method public boolean hasLeapSecond();
     method public boolean hasTimeUncertaintyNanos();
-    method public void reset();
-    method public void resetBiasNanos();
-    method public void resetBiasUncertaintyNanos();
-    method public void resetDriftNanosPerSecond();
-    method public void resetDriftUncertaintyNanosPerSecond();
-    method public void resetFullBiasNanos();
-    method public void resetLeapSecond();
-    method public void resetTimeUncertaintyNanos();
-    method public void set(android.location.GnssClock);
-    method public void setBiasNanos(double);
-    method public void setBiasUncertaintyNanos(double);
-    method public void setDriftNanosPerSecond(double);
-    method public void setDriftUncertaintyNanosPerSecond(double);
-    method public void setFullBiasNanos(long);
-    method public void setHardwareClockDiscontinuityCount(int);
-    method public void setLeapSecond(int);
-    method public void setTimeNanos(long);
-    method public void setTimeUncertaintyNanos(double);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
   }
@@ -20463,31 +20433,6 @@
     method public boolean hasCarrierPhaseUncertainty();
     method public boolean hasSnrInDb();
     method public boolean isPseudorangeRateCorrected();
-    method public void reset();
-    method public void resetCarrierCycles();
-    method public void resetCarrierFrequencyHz();
-    method public void resetCarrierPhase();
-    method public void resetCarrierPhaseUncertainty();
-    method public void resetSnrInDb();
-    method public void set(android.location.GnssMeasurement);
-    method public void setAccumulatedDeltaRangeMeters(double);
-    method public void setAccumulatedDeltaRangeState(int);
-    method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
-    method public void setCarrierCycles(long);
-    method public void setCarrierFrequencyHz(float);
-    method public void setCarrierPhase(double);
-    method public void setCarrierPhaseUncertainty(double);
-    method public void setCn0DbHz(double);
-    method public void setConstellationType(int);
-    method public void setMultipathIndicator(int);
-    method public void setPseudorangeRateMetersPerSecond(double);
-    method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
-    method public void setReceivedSvTimeNanos(long);
-    method public void setReceivedSvTimeUncertaintyNanos(long);
-    method public void setSnrInDb(double);
-    method public void setState(int);
-    method public void setSvid(int);
-    method public void setTimeOffsetNanos(double);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
     field public static final int ADR_STATE_RESET = 2; // 0x2
@@ -20537,14 +20482,6 @@
     method public int getSubmessageId();
     method public int getSvid();
     method public int getType();
-    method public void reset();
-    method public void set(android.location.GnssNavigationMessage);
-    method public void setData(byte[]);
-    method public void setMessageId(int);
-    method public void setStatus(int);
-    method public void setSubmessageId(int);
-    method public void setSvid(int);
-    method public void setType(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
     field public static final int STATUS_PARITY_PASSED = 1; // 0x1
@@ -21719,37 +21656,129 @@
     field public static final int ORIENTATION_TRANSVERSE = 7; // 0x7
     field public static final int ORIENTATION_UNDEFINED = 0; // 0x0
     field public static final java.lang.String TAG_APERTURE = "FNumber";
+    field public static final java.lang.String TAG_APERTURE_VALUE = "ApertureValue";
+    field public static final java.lang.String TAG_ARTIST = "Artist";
+    field public static final java.lang.String TAG_BITS_PER_SAMPLE = "BitsPerSample";
+    field public static final java.lang.String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
+    field public static final java.lang.String TAG_CFA_PATTERN = "CFAPattern";
+    field public static final java.lang.String TAG_COLOR_SPACE = "ColorSpace";
+    field public static final java.lang.String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
+    field public static final java.lang.String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
+    field public static final java.lang.String TAG_COMPRESSION = "Compression";
+    field public static final java.lang.String TAG_CONTRAST = "Contrast";
+    field public static final java.lang.String TAG_COPYRIGHT = "Copyright";
+    field public static final java.lang.String TAG_CUSTOM_RENDERED = "CustomRendered";
     field public static final java.lang.String TAG_DATETIME = "DateTime";
     field public static final java.lang.String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    field public static final java.lang.String TAG_DATETIME_ORIGINAL = "DateTimeOriginal";
+    field public static final java.lang.String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription";
     field public static final java.lang.String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+    field public static final java.lang.String TAG_EXIF_VERSION = "ExifVersion";
     field public static final java.lang.String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+    field public static final java.lang.String TAG_EXPOSURE_INDEX = "ExposureIndex";
     field public static final java.lang.String TAG_EXPOSURE_MODE = "ExposureMode";
     field public static final java.lang.String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
     field public static final java.lang.String TAG_EXPOSURE_TIME = "ExposureTime";
+    field public static final java.lang.String TAG_FILE_SOURCE = "FileSource";
     field public static final java.lang.String TAG_FLASH = "Flash";
+    field public static final java.lang.String TAG_FLASHPIX_VERSION = "FlashpixVersion";
+    field public static final java.lang.String TAG_FLASH_ENERGY = "FlashEnergy";
     field public static final java.lang.String TAG_FOCAL_LENGTH = "FocalLength";
+    field public static final java.lang.String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm";
+    field public static final java.lang.String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit";
+    field public static final java.lang.String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution";
+    field public static final java.lang.String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
+    field public static final java.lang.String TAG_F_NUMBER = "FNumber";
+    field public static final java.lang.String TAG_GAIN_CONTROL = "GainControl";
     field public static final java.lang.String TAG_GPS_ALTITUDE = "GPSAltitude";
     field public static final java.lang.String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
+    field public static final java.lang.String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
     field public static final java.lang.String TAG_GPS_DATESTAMP = "GPSDateStamp";
+    field public static final java.lang.String TAG_GPS_DEST_BEARING = "GPSDestBearing";
+    field public static final java.lang.String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef";
+    field public static final java.lang.String TAG_GPS_DEST_DISTANCE = "GPSDestDistance";
+    field public static final java.lang.String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef";
+    field public static final java.lang.String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude";
+    field public static final java.lang.String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef";
+    field public static final java.lang.String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude";
+    field public static final java.lang.String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
+    field public static final java.lang.String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
+    field public static final java.lang.String TAG_GPS_DOP = "GPSDOP";
+    field public static final java.lang.String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
+    field public static final java.lang.String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
     field public static final java.lang.String TAG_GPS_LATITUDE = "GPSLatitude";
     field public static final java.lang.String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
     field public static final java.lang.String TAG_GPS_LONGITUDE = "GPSLongitude";
     field public static final java.lang.String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    field public static final java.lang.String TAG_GPS_MAP_DATUM = "GPSMapDatum";
+    field public static final java.lang.String TAG_GPS_MEASURE_MODE = "GPSMeasureMode";
     field public static final java.lang.String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
+    field public static final java.lang.String TAG_GPS_SATELLITES = "GPSSatellites";
+    field public static final java.lang.String TAG_GPS_SPEED = "GPSSpeed";
+    field public static final java.lang.String TAG_GPS_SPEED_REF = "GPSSpeedRef";
+    field public static final java.lang.String TAG_GPS_STATUS = "GPSStatus";
     field public static final java.lang.String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+    field public static final java.lang.String TAG_GPS_TRACK = "GPSTrack";
+    field public static final java.lang.String TAG_GPS_TRACK_REF = "GPSTrackRef";
+    field public static final java.lang.String TAG_GPS_VERSION_ID = "GPSVersionID";
+    field public static final java.lang.String TAG_IMAGE_DESCRIPTION = "ImageDescription";
     field public static final java.lang.String TAG_IMAGE_LENGTH = "ImageLength";
+    field public static final java.lang.String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
     field public static final java.lang.String TAG_IMAGE_WIDTH = "ImageWidth";
+    field public static final java.lang.String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
     field public static final java.lang.String TAG_ISO = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
+    field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
     field public static final java.lang.String TAG_LIGHT_SOURCE = "LightSource";
     field public static final java.lang.String TAG_MAKE = "Make";
+    field public static final java.lang.String TAG_MAKER_NOTE = "MakerNote";
+    field public static final java.lang.String TAG_MAX_APERTURE_VALUE = "MaxApertureValue";
     field public static final java.lang.String TAG_METERING_MODE = "MeteringMode";
     field public static final java.lang.String TAG_MODEL = "Model";
+    field public static final java.lang.String TAG_OECF = "OECF";
     field public static final java.lang.String TAG_ORIENTATION = "Orientation";
+    field public static final java.lang.String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
+    field public static final java.lang.String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
+    field public static final java.lang.String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
+    field public static final java.lang.String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
+    field public static final java.lang.String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
+    field public static final java.lang.String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
+    field public static final java.lang.String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
+    field public static final java.lang.String TAG_RESOLUTION_UNIT = "ResolutionUnit";
+    field public static final java.lang.String TAG_ROWS_PER_STRIP = "RowsPerStrip";
+    field public static final java.lang.String TAG_SAMPLES_PER_PIXEL = "SamplesPerPixel";
+    field public static final java.lang.String TAG_SATURATION = "Saturation";
+    field public static final java.lang.String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
+    field public static final java.lang.String TAG_SCENE_TYPE = "SceneType";
+    field public static final java.lang.String TAG_SENSING_METHOD = "SensingMethod";
+    field public static final java.lang.String TAG_SHARPNESS = "Sharpness";
+    field public static final java.lang.String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
+    field public static final java.lang.String TAG_SOFTWARE = "Software";
+    field public static final java.lang.String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
+    field public static final java.lang.String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
+    field public static final java.lang.String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
+    field public static final java.lang.String TAG_STRIP_OFFSETS = "StripOffsets";
+    field public static final java.lang.String TAG_SUBJECT_AREA = "SubjectArea";
     field public static final java.lang.String TAG_SUBJECT_DISTANCE = "SubjectDistance";
+    field public static final java.lang.String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange";
+    field public static final java.lang.String TAG_SUBJECT_LOCATION = "SubjectLocation";
     field public static final java.lang.String TAG_SUBSEC_TIME = "SubSecTime";
     field public static final java.lang.String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
+    field public static final java.lang.String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized";
     field public static final java.lang.String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
+    field public static final java.lang.String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
+    field public static final java.lang.String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
+    field public static final java.lang.String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
+    field public static final java.lang.String TAG_TRANSFER_FUNCTION = "TransferFunction";
+    field public static final java.lang.String TAG_USER_COMMENT = "UserComment";
     field public static final java.lang.String TAG_WHITE_BALANCE = "WhiteBalance";
+    field public static final java.lang.String TAG_WHITE_POINT = "WhitePoint";
+    field public static final java.lang.String TAG_X_RESOLUTION = "XResolution";
+    field public static final java.lang.String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients";
+    field public static final java.lang.String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
+    field public static final java.lang.String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
+    field public static final java.lang.String TAG_Y_RESOLUTION = "YResolution";
     field public static final int WHITEBALANCE_AUTO = 0; // 0x0
     field public static final int WHITEBALANCE_MANUAL = 1; // 0x1
   }
@@ -22475,6 +22504,7 @@
     field public static final java.lang.String KEY_DURATION = "durationUs";
     field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
     field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
+    field public static final java.lang.String KEY_HDR_STATIC_INFO = "hdr-static-info";
     field public static final java.lang.String KEY_HEIGHT = "height";
     field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
     field public static final java.lang.String KEY_IS_ADTS = "is-adts";
@@ -23777,6 +23807,7 @@
   public static class AudioMix.Builder {
     ctor public AudioMix.Builder(android.media.audiopolicy.AudioMixingRule) throws java.lang.IllegalArgumentException;
     method public android.media.audiopolicy.AudioMix build() throws java.lang.IllegalArgumentException;
+    method public android.media.audiopolicy.AudioMix.Builder setDevice(android.media.AudioDeviceInfo) throws java.lang.IllegalArgumentException;
     method public android.media.audiopolicy.AudioMix.Builder setFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
     method public android.media.audiopolicy.AudioMix.Builder setRouteFlags(int) throws java.lang.IllegalArgumentException;
   }
@@ -31360,7 +31391,6 @@
     ctor public PersistableBundle();
     ctor public PersistableBundle(int);
     ctor public PersistableBundle(android.os.PersistableBundle);
-    ctor public PersistableBundle(android.os.Bundle);
     method public java.lang.Object clone();
     method public int describeContents();
     method public android.os.PersistableBundle getPersistableBundle(java.lang.String);
@@ -31758,6 +31788,147 @@
 
 }
 
+package android.os.health {
+
+  public class HealthStats {
+    method public java.lang.String getDataType();
+    method public long getMeasurement(int);
+    method public int getMeasurementKeyAt(int);
+    method public int getMeasurementKeyCount();
+    method public java.util.Map<java.lang.String, java.lang.Long> getMeasurements(int);
+    method public int getMeasurementsKeyAt(int);
+    method public int getMeasurementsKeyCount();
+    method public java.util.Map<java.lang.String, android.os.health.HealthStats> getStats(int);
+    method public int getStatsKeyAt(int);
+    method public int getStatsKeyCount();
+    method public android.os.health.TimerStat getTimer(int);
+    method public int getTimerCount(int);
+    method public int getTimerKeyAt(int);
+    method public int getTimerKeyCount();
+    method public long getTimerTime(int);
+    method public java.util.Map<java.lang.String, android.os.health.TimerStat> getTimers(int);
+    method public int getTimersKeyAt(int);
+    method public int getTimersKeyCount();
+    method public boolean hasMeasurement(int);
+    method public boolean hasMeasurements(int);
+    method public boolean hasStats(int);
+    method public boolean hasTimer(int);
+    method public boolean hasTimers(int);
+  }
+
+  public final class PackageHealthStats {
+    field public static final int MEASUREMENTS_WAKEUP_ALARMS_COUNT = 40002; // 0x9c42
+    field public static final int STATS_SERVICES = 40001; // 0x9c41
+  }
+
+  public final class PidHealthStats {
+    field public static final int MEASUREMENT_WAKE_NESTING_COUNT = 20001; // 0x4e21
+    field public static final int MEASUREMENT_WAKE_START_MS = 20003; // 0x4e23
+    field public static final int MEASUREMENT_WAKE_SUM_MS = 20002; // 0x4e22
+  }
+
+  public final class ProcessHealthStats {
+    field public static final int MEASUREMENT_ANR_COUNT = 30005; // 0x7535
+    field public static final int MEASUREMENT_CRASHES_COUNT = 30004; // 0x7534
+    field public static final int MEASUREMENT_FOREGROUND_MS = 30006; // 0x7536
+    field public static final int MEASUREMENT_STARTS_COUNT = 30003; // 0x7533
+    field public static final int MEASUREMENT_SYSTEM_TIME_MS = 30002; // 0x7532
+    field public static final int MEASUREMENT_USER_TIME_MS = 30001; // 0x7531
+  }
+
+  public final class ServiceHealthStats {
+    field public static final int MEASUREMENT_LAUNCH_COUNT = 50002; // 0xc352
+    field public static final int MEASUREMENT_START_SERVICE_COUNT = 50001; // 0xc351
+  }
+
+  public class SystemHealthManager {
+    method public static android.os.health.SystemHealthManager from(android.content.Context);
+    method public android.os.health.HealthStats takeMyUidSnapshot();
+    method public android.os.health.HealthStats takeUidSnapshot(int);
+    method public android.os.health.HealthStats[] takeUidSnapshots(int[]);
+  }
+
+  public class TimerStat implements android.os.Parcelable {
+    ctor public TimerStat();
+    ctor public TimerStat(int, long);
+    ctor public TimerStat(android.os.Parcel);
+    method public int describeContents();
+    method public int getCount();
+    method public long getTime();
+    method public void setCount(int);
+    method public void setTime(long);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.os.health.TimerStat> CREATOR;
+  }
+
+  public final class UidHealthStats {
+    field public static final int MEASUREMENT_BLUETOOTH_IDLE_MS = 10020; // 0x2724
+    field public static final int MEASUREMENT_BLUETOOTH_POWER_MAMS = 10023; // 0x2727
+    field public static final int MEASUREMENT_BLUETOOTH_RX_BYTES = 10052; // 0x2744
+    field public static final int MEASUREMENT_BLUETOOTH_RX_MS = 10021; // 0x2725
+    field public static final int MEASUREMENT_BLUETOOTH_RX_PACKETS = 10058; // 0x274a
+    field public static final int MEASUREMENT_BLUETOOTH_TX_BYTES = 10053; // 0x2745
+    field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
+    field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
+    field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
+    field public static final int MEASUREMENT_CPU_POWER_MAUS = 10064; // 0x2750
+    field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
+    field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
+    field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
+    field public static final int MEASUREMENT_MOBILE_RX_MS = 10025; // 0x2729
+    field public static final int MEASUREMENT_MOBILE_RX_PACKETS = 10054; // 0x2746
+    field public static final int MEASUREMENT_MOBILE_TX_BYTES = 10049; // 0x2741
+    field public static final int MEASUREMENT_MOBILE_TX_MS = 10026; // 0x272a
+    field public static final int MEASUREMENT_MOBILE_TX_PACKETS = 10055; // 0x2747
+    field public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = 10045; // 0x273d
+    field public static final int MEASUREMENT_REALTIME_BATTERY_MS = 10001; // 0x2711
+    field public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = 10003; // 0x2713
+    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = 10063; // 0x274f
+    field public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = 10047; // 0x273f
+    field public static final int MEASUREMENT_UPTIME_BATTERY_MS = 10002; // 0x2712
+    field public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = 10004; // 0x2714
+    field public static final int MEASUREMENT_USER_CPU_TIME_US = 10062; // 0x274e
+    field public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = 10029; // 0x272d
+    field public static final int MEASUREMENT_WIFI_IDLE_MS = 10016; // 0x2720
+    field public static final int MEASUREMENT_WIFI_MULTICAST_MS = 10031; // 0x272f
+    field public static final int MEASUREMENT_WIFI_POWER_MAMS = 10019; // 0x2723
+    field public static final int MEASUREMENT_WIFI_RUNNING_MS = 10028; // 0x272c
+    field public static final int MEASUREMENT_WIFI_RX_BYTES = 10050; // 0x2742
+    field public static final int MEASUREMENT_WIFI_RX_MS = 10017; // 0x2721
+    field public static final int MEASUREMENT_WIFI_RX_PACKETS = 10056; // 0x2748
+    field public static final int MEASUREMENT_WIFI_TX_BYTES = 10051; // 0x2743
+    field public static final int MEASUREMENT_WIFI_TX_MS = 10018; // 0x2722
+    field public static final int MEASUREMENT_WIFI_TX_PACKETS = 10057; // 0x2749
+    field public static final int STATS_PACKAGES = 10015; // 0x271f
+    field public static final int STATS_PIDS = 10013; // 0x271d
+    field public static final int STATS_PROCESSES = 10014; // 0x271e
+    field public static final int TIMERS_JOBS = 10010; // 0x271a
+    field public static final int TIMERS_SENSORS = 10012; // 0x271c
+    field public static final int TIMERS_SYNCS = 10009; // 0x2719
+    field public static final int TIMERS_WAKELOCKS_DRAW = 10008; // 0x2718
+    field public static final int TIMERS_WAKELOCKS_FULL = 10005; // 0x2715
+    field public static final int TIMERS_WAKELOCKS_PARTIAL = 10006; // 0x2716
+    field public static final int TIMERS_WAKELOCKS_WINDOW = 10007; // 0x2717
+    field public static final int TIMER_AUDIO = 10032; // 0x2730
+    field public static final int TIMER_BLUETOOTH_SCAN = 10037; // 0x2735
+    field public static final int TIMER_CAMERA = 10035; // 0x2733
+    field public static final int TIMER_FLASHLIGHT = 10034; // 0x2732
+    field public static final int TIMER_FOREGROUND_ACTIVITY = 10036; // 0x2734
+    field public static final int TIMER_GPS_SENSOR = 10011; // 0x271b
+    field public static final int TIMER_MOBILE_RADIO_ACTIVE = 10061; // 0x274d
+    field public static final int TIMER_PROCESS_STATE_BACKGROUND_MS = 10042; // 0x273a
+    field public static final int TIMER_PROCESS_STATE_CACHED_MS = 10043; // 0x273b
+    field public static final int TIMER_PROCESS_STATE_FOREGROUND_MS = 10041; // 0x2739
+    field public static final int TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS = 10039; // 0x2737
+    field public static final int TIMER_PROCESS_STATE_TOP_MS = 10038; // 0x2736
+    field public static final int TIMER_PROCESS_STATE_TOP_SLEEPING_MS = 10040; // 0x2738
+    field public static final int TIMER_VIBRATOR = 10044; // 0x273c
+    field public static final int TIMER_VIDEO = 10033; // 0x2731
+    field public static final int TIMER_WIFI_SCAN = 10030; // 0x272e
+  }
+
+}
+
 package android.os.storage {
 
   public abstract class OnObbStateChangeListener {
@@ -32920,6 +33091,7 @@
   public static class CallLog.Calls implements android.provider.BaseColumns {
     ctor public CallLog.Calls();
     method public static java.lang.String getLastOutgoingCall(android.content.Context);
+    field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7
     field public static final int BLOCKED_TYPE = 6; // 0x6
     field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number";
     field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri";
@@ -32942,6 +33114,7 @@
     field public static final java.lang.String DURATION = "duration";
     field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER";
     field public static final java.lang.String FEATURES = "features";
+    field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2
     field public static final int FEATURES_VIDEO = 1; // 0x1
     field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location";
     field public static final int INCOMING_TYPE = 1; // 0x1
@@ -34717,7 +34890,6 @@
     field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS";
     field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS";
     field public static final java.lang.String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
-    field public static final java.lang.String ACTION_SCREEN_READER_TUTORIAL = "android.settings.SCREEN_READER_TUTORIAL";
     field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
     field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS";
     field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";
@@ -38464,10 +38636,12 @@
     method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
+    method public void pullExternalCall();
     method public void registerCallback(android.telecom.Call.Callback);
     method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
     method public void reject(boolean, java.lang.String);
     method public deprecated void removeListener(android.telecom.Call.Listener);
+    method public void sendCallEvent(java.lang.String, android.os.Bundle);
     method public void splitFromConference();
     method public void stopDtmfTone();
     method public void swapConference();
@@ -38482,6 +38656,7 @@
     field public static final int STATE_HOLDING = 3; // 0x3
     field public static final int STATE_NEW = 0; // 0x0
     field public static final deprecated int STATE_PRE_DIAL_WAIT = 8; // 0x8
+    field public static final int STATE_PULLING_CALL = 11; // 0xb
     field public static final int STATE_RINGING = 2; // 0x2
     field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8
   }
@@ -38492,6 +38667,7 @@
     method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List<java.lang.String>);
     method public void onChildrenChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
     method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
+    method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
     method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
     method public void onParentChanged(android.telecom.Call, android.telecom.Call);
     method public void onPostDialWait(android.telecom.Call, java.lang.String);
@@ -38522,6 +38698,7 @@
     method public static java.lang.String propertiesToString(int);
     field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+    field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
@@ -38541,6 +38718,7 @@
     field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4
     field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
     field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
+    field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
     field public static final int PROPERTY_WIFI = 8; // 0x8
     field public static final int PROPERTY_WORK_CALL = 32; // 0x20
   }
@@ -38666,15 +38844,19 @@
     method public void onAnswer();
     method public deprecated void onAudioStateChanged(android.telecom.AudioState);
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
+    method public void onCallEvent(java.lang.String, android.os.Bundle);
     method public void onDisconnect();
     method public void onHold();
     method public void onPlayDtmfTone(char);
     method public void onPostDialContinue(boolean);
+    method public void onPullExternalCall();
     method public void onReject();
+    method public void onReject(java.lang.String);
     method public void onSeparate();
     method public void onStateChanged(int);
     method public void onStopDtmfTone();
     method public void onUnhold();
+    method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
     method public final void setActive();
     method public final void setAddress(android.net.Uri, int);
     method public final void setAudioModeIsVoip(boolean);
@@ -38698,9 +38880,12 @@
     method public static java.lang.String stateToString(int);
     field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+    field public static final int CAPABILITY_CAN_PULL_CALL = 33554432; // 0x2000000
+    field public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 4194304; // 0x400000
     field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
+    field public static final int CAPABILITY_IS_EXTERNAL_CALL = 16777216; // 0x1000000
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
     field public static final int CAPABILITY_MERGE_CONFERENCE = 4; // 0x4
     field public static final int CAPABILITY_MUTE = 64; // 0x40
@@ -38714,6 +38899,7 @@
     field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
+    field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
     field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
     field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
     field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -38723,6 +38909,7 @@
     field public static final int STATE_HOLDING = 5; // 0x5
     field public static final int STATE_INITIALIZING = 0; // 0x0
     field public static final int STATE_NEW = 1; // 0x1
+    field public static final int STATE_PULLING_CALL = 7; // 0x7
     field public static final int STATE_RINGING = 2; // 0x2
   }
 
@@ -38800,7 +38987,9 @@
     method public java.lang.String getReason();
     method public int getTone();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ANSWERED_ELSEWHERE = 11; // 0xb
     field public static final int BUSY = 7; // 0x7
+    field public static final int CALL_PULLED = 12; // 0xc
     field public static final int CANCELED = 4; // 0x4
     field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa
     field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR;
@@ -38837,6 +39026,7 @@
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
     method public void onCallRemoved(android.telecom.Call);
     method public void onCanAddCallChanged(boolean);
+    method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
     method public deprecated void onPhoneCreated(android.telecom.Phone);
     method public deprecated void onPhoneDestroyed(android.telecom.Phone);
     method public void onSilenceRinger();
@@ -39042,6 +39232,7 @@
     method public boolean isVoipAudioMode();
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
+    method public void pullExternalCall();
     method public void registerCallback(android.telecom.RemoteConnection.Callback);
     method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler);
     method public void reject();
@@ -39059,6 +39250,7 @@
     method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference);
     method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List<android.telecom.RemoteConnection>);
     method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int);
+    method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle);
     method public void onDestroyed(android.telecom.RemoteConnection);
     method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause);
     method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle);
@@ -39183,6 +39375,7 @@
     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 java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -39326,6 +39519,7 @@
     field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
     field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
     field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
+    field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
     field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
     field public static final java.lang.String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
     field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
@@ -45154,6 +45348,7 @@
     method public void onStartTemporaryDetach();
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
+    method public void onVisibilityAggregated(boolean);
     method protected void onVisibilityChanged(android.view.View, int);
     method public void onWindowFocusChanged(boolean);
     method public void onWindowSystemUiVisibilityChanged(int);
@@ -46251,7 +46446,7 @@
     method public abstract boolean onMenuOpened(int, android.view.Menu);
     method public abstract void onPanelClosed(int, android.view.Menu);
     method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
+    method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public abstract boolean onSearchRequested();
     method public abstract boolean onSearchRequested(android.view.SearchEvent);
     method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
@@ -48505,12 +48700,13 @@
     ctor public WebViewFactory();
     method public static android.content.pm.PackageInfo getLoadedPackageInfo();
     method public static java.lang.String getWebViewPackageName();
-    method public static int loadWebViewNativeLibraryFromPackage(java.lang.String);
+    method public static int loadWebViewNativeLibraryFromPackage(java.lang.String, java.lang.ClassLoader);
     method public static void prepareWebViewInZygote();
     field public static final java.lang.String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY = "persist.sys.webview.vmsize";
     field public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2; // 0x2
     field public static final int LIBLOAD_FAILED_JNI_CALL = 7; // 0x7
     field public static final int LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES = 4; // 0x4
+    field public static final int LIBLOAD_FAILED_TO_FIND_NAMESPACE = 10; // 0xa
     field public static final int LIBLOAD_FAILED_TO_LOAD_LIBRARY = 6; // 0x6
     field public static final int LIBLOAD_FAILED_TO_OPEN_RELRO_FILE = 5; // 0x5
     field public static final int LIBLOAD_FAILED_WAITING_FOR_RELRO = 3; // 0x3
@@ -53818,6 +54014,7 @@
   public abstract interface Iterable {
     method public default void forEach(java.util.function.Consumer<? super T>);
     method public abstract java.util.Iterator<T> iterator();
+    method public default java.util.Spliterator<T> spliterator();
   }
 
   public class LinkageError extends java.lang.Error {
@@ -60238,6 +60435,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class ArrayList extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
@@ -60248,7 +60446,9 @@
     method public void ensureCapacity(int);
     method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
+    method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public void trimToSize();
   }
 
@@ -60331,6 +60531,24 @@
     method public static int hashCode(float[]);
     method public static int hashCode(double[]);
     method public static int hashCode(java.lang.Object[]);
+    method public static void parallelSort(byte[]);
+    method public static void parallelSort(byte[], int, int);
+    method public static void parallelSort(char[]);
+    method public static void parallelSort(char[], int, int);
+    method public static void parallelSort(short[]);
+    method public static void parallelSort(short[], int, int);
+    method public static void parallelSort(int[]);
+    method public static void parallelSort(int[], int, int);
+    method public static void parallelSort(long[]);
+    method public static void parallelSort(long[], int, int);
+    method public static void parallelSort(float[]);
+    method public static void parallelSort(float[], int, int);
+    method public static void parallelSort(double[]);
+    method public static void parallelSort(double[], int, int);
+    method public static void parallelSort(T[]);
+    method public static void parallelSort(T[], int, int);
+    method public static void parallelSort(T[], java.util.Comparator<? super T>);
+    method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
     method public static void sort(int[]);
     method public static void sort(int[], int, int);
     method public static void sort(long[]);
@@ -60349,6 +60567,14 @@
     method public static void sort(java.lang.Object[], int, int);
     method public static void sort(T[], java.util.Comparator<? super T>);
     method public static void sort(T[], int, int, java.util.Comparator<? super T>);
+    method public static java.util.Spliterator<T> spliterator(T[]);
+    method public static java.util.Spliterator<T> spliterator(T[], int, int);
+    method public static java.util.Spliterator.OfInt spliterator(int[]);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int, int);
+    method public static java.util.Spliterator.OfLong spliterator(long[]);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int, int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[]);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
     method public static java.lang.String toString(long[]);
     method public static java.lang.String toString(int[]);
     method public static java.lang.String toString(short[]);
@@ -60510,6 +60736,7 @@
     method public abstract java.util.Iterator<E> iterator();
     method public abstract boolean remove(java.lang.Object);
     method public abstract boolean removeAll(java.util.Collection<?>);
+    method public default boolean removeIf(java.util.function.Predicate<? super E>);
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
     method public abstract java.lang.Object[] toArray();
@@ -60848,6 +61075,7 @@
     method public java.lang.Object clone();
     method public java.util.Iterator<E> iterator();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class Hashtable extends java.util.Dictionary implements java.lang.Cloneable java.util.Map java.io.Serializable {
@@ -60992,6 +61220,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public abstract interface List implements java.util.Collection {
@@ -61141,23 +61370,37 @@
 
   public abstract interface Map {
     method public abstract void clear();
+    method public default V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public default V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public default V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public abstract boolean containsKey(java.lang.Object);
     method public abstract boolean containsValue(java.lang.Object);
     method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public abstract boolean equals(java.lang.Object);
     method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public abstract V get(java.lang.Object);
+    method public default V getOrDefault(java.lang.Object, V);
     method public abstract int hashCode();
     method public abstract boolean isEmpty();
     method public abstract java.util.Set<K> keySet();
+    method public default V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public abstract V put(K, V);
     method public abstract void putAll(java.util.Map<? extends K, ? extends V>);
+    method public default V putIfAbsent(K, V);
     method public abstract V remove(java.lang.Object);
+    method public default boolean remove(java.lang.Object, java.lang.Object);
+    method public default boolean replace(K, V, V);
+    method public default V replace(K, V);
+    method public default void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public abstract int size();
     method public abstract java.util.Collection<V> values();
   }
 
   public static abstract interface Map.Entry {
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue();
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>);
     method public abstract boolean equals(java.lang.Object);
     method public abstract K getKey();
     method public abstract V getValue();
@@ -61336,6 +61579,7 @@
   public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
+    ctor public PriorityQueue(java.util.Comparator<? super E>);
     ctor public PriorityQueue(int, java.util.Comparator<? super E>);
     ctor public PriorityQueue(java.util.Collection<? extends E>);
     ctor public PriorityQueue(java.util.PriorityQueue<? extends E>);
@@ -61346,6 +61590,7 @@
     method public E peek();
     method public E poll();
     method public int size();
+    method public final java.util.Spliterator<E> spliterator();
   }
 
   public class Properties extends java.util.Hashtable {
@@ -61588,6 +61833,111 @@
     method public abstract java.util.SortedSet<E> tailSet(E);
   }
 
+  public abstract interface Spliterator {
+    method public abstract int characteristics();
+    method public abstract long estimateSize();
+    method public default void forEachRemaining(java.util.function.Consumer<? super T>);
+    method public default java.util.Comparator<? super T> getComparator();
+    method public default long getExactSizeIfKnown();
+    method public default boolean hasCharacteristics(int);
+    method public abstract boolean tryAdvance(java.util.function.Consumer<? super T>);
+    method public abstract java.util.Spliterator<T> trySplit();
+    field public static final int CONCURRENT = 4096; // 0x1000
+    field public static final int DISTINCT = 1; // 0x1
+    field public static final int IMMUTABLE = 1024; // 0x400
+    field public static final int NONNULL = 256; // 0x100
+    field public static final int ORDERED = 16; // 0x10
+    field public static final int SIZED = 64; // 0x40
+    field public static final int SORTED = 4; // 0x4
+    field public static final int SUBSIZED = 16384; // 0x4000
+  }
+
+  public static abstract interface Spliterator.OfDouble implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.DoubleConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+    method public abstract boolean tryAdvance(java.util.function.DoubleConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Double>);
+    method public abstract java.util.Spliterator.OfDouble trySplit();
+  }
+
+  public static abstract interface Spliterator.OfInt implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.IntConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+    method public abstract boolean tryAdvance(java.util.function.IntConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Integer>);
+    method public abstract java.util.Spliterator.OfInt trySplit();
+  }
+
+  public static abstract interface Spliterator.OfLong implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.LongConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+    method public abstract boolean tryAdvance(java.util.function.LongConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Long>);
+    method public abstract java.util.Spliterator.OfLong trySplit();
+  }
+
+  public static abstract interface Spliterator.OfPrimitive implements java.util.Spliterator {
+    method public default void forEachRemaining(T_CONS);
+    method public abstract boolean tryAdvance(T_CONS);
+    method public abstract T_SPLITR trySplit();
+  }
+
+  public final class Spliterators {
+    method public static java.util.Spliterator.OfDouble emptyDoubleSpliterator();
+    method public static java.util.Spliterator.OfInt emptyIntSpliterator();
+    method public static java.util.Spliterator.OfLong emptyLongSpliterator();
+    method public static java.util.Spliterator<T> emptySpliterator();
+    method public static java.util.Iterator<T> iterator(java.util.Spliterator<? extends T>);
+    method public static java.util.PrimitiveIterator.OfInt iterator(java.util.Spliterator.OfInt);
+    method public static java.util.PrimitiveIterator.OfLong iterator(java.util.Spliterator.OfLong);
+    method public static java.util.PrimitiveIterator.OfDouble iterator(java.util.Spliterator.OfDouble);
+    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int);
+    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int, int, int);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int, int, int);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int, int, int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int, int, int);
+    method public static java.util.Spliterator<T> spliterator(java.util.Collection<? extends T>, int);
+    method public static java.util.Spliterator<T> spliterator(java.util.Iterator<? extends T>, long, int);
+    method public static java.util.Spliterator.OfInt spliterator(java.util.PrimitiveIterator.OfInt, long, int);
+    method public static java.util.Spliterator.OfLong spliterator(java.util.PrimitiveIterator.OfLong, long, int);
+    method public static java.util.Spliterator.OfDouble spliterator(java.util.PrimitiveIterator.OfDouble, long, int);
+    method public static java.util.Spliterator<T> spliteratorUnknownSize(java.util.Iterator<? extends T>, int);
+    method public static java.util.Spliterator.OfInt spliteratorUnknownSize(java.util.PrimitiveIterator.OfInt, int);
+    method public static java.util.Spliterator.OfLong spliteratorUnknownSize(java.util.PrimitiveIterator.OfLong, int);
+    method public static java.util.Spliterator.OfDouble spliteratorUnknownSize(java.util.PrimitiveIterator.OfDouble, int);
+  }
+
+  public static abstract class Spliterators.AbstractDoubleSpliterator implements java.util.Spliterator.OfDouble {
+    ctor protected Spliterators.AbstractDoubleSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfDouble trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractIntSpliterator implements java.util.Spliterator.OfInt {
+    ctor protected Spliterators.AbstractIntSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfInt trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractLongSpliterator implements java.util.Spliterator.OfLong {
+    ctor protected Spliterators.AbstractLongSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfLong trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractSpliterator implements java.util.Spliterator {
+    ctor protected Spliterators.AbstractSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator<T> trySplit();
+  }
+
   public class Stack extends java.util.Vector {
     ctor public Stack();
     method public boolean empty();
@@ -61597,6 +61947,15 @@
     method public synchronized int search(java.lang.Object);
   }
 
+  public final class StringJoiner {
+    ctor public StringJoiner(java.lang.CharSequence);
+    ctor public StringJoiner(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence);
+    method public java.util.StringJoiner add(java.lang.CharSequence);
+    method public int length();
+    method public java.util.StringJoiner merge(java.util.StringJoiner);
+    method public java.util.StringJoiner setEmptyValue(java.lang.CharSequence);
+  }
+
   public class StringTokenizer implements java.util.Enumeration {
     ctor public StringTokenizer(java.lang.String, java.lang.String, boolean);
     ctor public StringTokenizer(java.lang.String, java.lang.String);
@@ -61718,6 +62077,7 @@
     method public E pollFirst();
     method public E pollLast();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
     method public java.util.SortedSet<E> subSet(E, E);
     method public java.util.NavigableSet<E> tailSet(E, boolean);
@@ -61771,9 +62131,11 @@
     method public synchronized void removeAllElements();
     method public synchronized boolean removeElement(java.lang.Object);
     method public synchronized void removeElementAt(int);
+    method public synchronized boolean removeIf(java.util.function.Predicate<? super E>);
     method public synchronized void setElementAt(E, int);
     method public synchronized void setSize(int);
     method public synchronized int size();
+    method public java.util.Spliterator<E> spliterator();
     method public synchronized void trimToSize();
     field protected int capacityIncrement;
     field protected int elementCount;
@@ -61821,6 +62183,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -61884,6 +62247,78 @@
     ctor public CancellationException(java.lang.String);
   }
 
+  public class CompletableFuture implements java.util.concurrent.CompletionStage java.util.concurrent.Future {
+    ctor public CompletableFuture();
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> allOf(java.util.concurrent.CompletableFuture<?>...);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Object> anyOf(java.util.concurrent.CompletableFuture<?>...);
+    method public java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public boolean cancel(boolean);
+    method public boolean complete(T);
+    method public boolean completeExceptionally(java.lang.Throwable);
+    method public static java.util.concurrent.CompletableFuture<U> completedFuture(U);
+    method public java.util.concurrent.CompletableFuture<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
+    method public T get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public T get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public T getNow(T);
+    method public int getNumberOfDependents();
+    method public java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public boolean isCancelled();
+    method public boolean isCompletedExceptionally();
+    method public boolean isDone();
+    method public T join();
+    method public void obtrudeException(java.lang.Throwable);
+    method public void obtrudeValue(T);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>);
+    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRun(java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<T> toCompletableFuture();
+    method public java.util.concurrent.CompletableFuture<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
+  }
+
+  public static abstract interface CompletableFuture.AsynchronousCompletionTask {
+  }
+
+  public class CompletionException extends java.lang.RuntimeException {
+    ctor protected CompletionException();
+    ctor protected CompletionException(java.lang.String);
+    ctor public CompletionException(java.lang.String, java.lang.Throwable);
+    ctor public CompletionException(java.lang.Throwable);
+  }
+
   public abstract interface CompletionService {
     method public abstract java.util.concurrent.Future<V> poll();
     method public abstract java.util.concurrent.Future<V> poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
@@ -61892,20 +62327,130 @@
     method public abstract java.util.concurrent.Future<V> take() throws java.lang.InterruptedException;
   }
 
+  public abstract interface CompletionStage {
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
+    method public abstract java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRun(java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletableFuture<T> toCompletableFuture();
+    method public abstract java.util.concurrent.CompletionStage<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
+  }
+
   public class ConcurrentHashMap extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable {
     ctor public ConcurrentHashMap();
     ctor public ConcurrentHashMap(int);
     ctor public ConcurrentHashMap(java.util.Map<? extends K, ? extends V>);
     ctor public ConcurrentHashMap(int, float);
     ctor public ConcurrentHashMap(int, float, int);
+    method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public boolean contains(java.lang.Object);
     method public java.util.Enumeration<V> elements();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public void forEach(long, java.util.function.BiConsumer<? super K, ? super V>);
+    method public void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachEntry(long, java.util.function.Consumer<? super java.util.Map.Entry<K, V>>);
+    method public void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachKey(long, java.util.function.Consumer<? super K>);
+    method public void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachValue(long, java.util.function.Consumer<? super V>);
+    method public void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public V getOrDefault(java.lang.Object, V);
+    method public java.util.concurrent.ConcurrentHashMap.KeySetView<K, V> keySet(V);
     method public java.util.Enumeration<K> keys();
+    method public long mappingCount();
+    method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
+    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet();
+    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int);
     method public V putIfAbsent(K, V);
+    method public U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public java.util.Map.Entry<K, V> reduceEntries(long, java.util.function.BiFunction<java.util.Map.Entry<K, V>, java.util.Map.Entry<K, V>, ? extends java.util.Map.Entry<K, V>>);
+    method public U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceEntriesToDouble(long, java.util.function.ToDoubleFunction<java.util.Map.Entry<K, V>>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceEntriesToInt(long, java.util.function.ToIntFunction<java.util.Map.Entry<K, V>>, int, java.util.function.IntBinaryOperator);
+    method public long reduceEntriesToLong(long, java.util.function.ToLongFunction<java.util.Map.Entry<K, V>>, long, java.util.function.LongBinaryOperator);
+    method public K reduceKeys(long, java.util.function.BiFunction<? super K, ? super K, ? extends K>);
+    method public U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceKeysToDouble(long, java.util.function.ToDoubleFunction<? super K>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceKeysToInt(long, java.util.function.ToIntFunction<? super K>, int, java.util.function.IntBinaryOperator);
+    method public long reduceKeysToLong(long, java.util.function.ToLongFunction<? super K>, long, java.util.function.LongBinaryOperator);
+    method public double reduceToDouble(long, java.util.function.ToDoubleBiFunction<? super K, ? super V>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceToInt(long, java.util.function.ToIntBiFunction<? super K, ? super V>, int, java.util.function.IntBinaryOperator);
+    method public long reduceToLong(long, java.util.function.ToLongBiFunction<? super K, ? super V>, long, java.util.function.LongBinaryOperator);
+    method public V reduceValues(long, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
+    method public U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceValuesToDouble(long, java.util.function.ToDoubleFunction<? super V>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceValuesToInt(long, java.util.function.ToIntFunction<? super V>, int, java.util.function.IntBinaryOperator);
+    method public long reduceValuesToLong(long, java.util.function.ToLongFunction<? super V>, long, java.util.function.LongBinaryOperator);
     method public boolean remove(java.lang.Object, java.lang.Object);
     method public boolean replace(K, V, V);
     method public V replace(K, V);
+    method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>);
+    method public U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>);
+    method public U searchKeys(long, java.util.function.Function<? super K, ? extends U>);
+    method public U searchValues(long, java.util.function.Function<? super V, ? extends U>);
+  }
+
+   static abstract class ConcurrentHashMap.CollectionView implements java.util.Collection java.io.Serializable {
+    method public final void clear();
+    method public abstract boolean contains(java.lang.Object);
+    method public final boolean containsAll(java.util.Collection<?>);
+    method public java.util.concurrent.ConcurrentHashMap<K, V> getMap();
+    method public final boolean isEmpty();
+    method public abstract java.util.Iterator<E> iterator();
+    method public abstract boolean remove(java.lang.Object);
+    method public final boolean removeAll(java.util.Collection<?>);
+    method public final boolean retainAll(java.util.Collection<?>);
+    method public final int size();
+    method public final java.lang.Object[] toArray();
+    method public final T[] toArray(T[]);
+    method public final java.lang.String toString();
+  }
+
+  public static class ConcurrentHashMap.KeySetView extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set {
+    method public boolean add(K);
+    method public boolean addAll(java.util.Collection<? extends K>);
+    method public boolean contains(java.lang.Object);
+    method public void forEach(java.util.function.Consumer<? super K>);
+    method public V getMappedValue();
+    method public java.util.Iterator<K> iterator();
+    method public boolean remove(java.lang.Object);
+    method public java.util.Spliterator<K> spliterator();
   }
 
   public class ConcurrentLinkedDeque extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable {
@@ -61935,6 +62480,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable {
@@ -61945,6 +62491,7 @@
     method public E peek();
     method public E poll();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public abstract interface ConcurrentMap implements java.util.Map {
@@ -61976,6 +62523,9 @@
     method public K ceilingKey(K);
     method public java.util.concurrent.ConcurrentSkipListMap<K, V> clone();
     method public java.util.Comparator<? super K> comparator();
+    method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public java.util.NavigableSet<K> descendingKeySet();
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> descendingMap();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
@@ -61983,6 +62533,8 @@
     method public K firstKey();
     method public java.util.Map.Entry<K, V> floorEntry(K);
     method public K floorKey(K);
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public V getOrDefault(java.lang.Object, V);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K, boolean);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K);
     method public java.util.Map.Entry<K, V> higherEntry(K);
@@ -61991,6 +62543,7 @@
     method public K lastKey();
     method public java.util.Map.Entry<K, V> lowerEntry(K);
     method public K lowerKey(K);
+    method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public java.util.NavigableSet<K> navigableKeySet();
     method public java.util.Map.Entry<K, V> pollFirstEntry();
     method public java.util.Map.Entry<K, V> pollLastEntry();
@@ -61998,6 +62551,7 @@
     method public boolean remove(java.lang.Object, java.lang.Object);
     method public boolean replace(K, V, V);
     method public V replace(K, V);
+    method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, boolean, K, boolean);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, K);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K, boolean);
@@ -62025,6 +62579,7 @@
     method public E pollFirst();
     method public E pollLast();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
     method public java.util.NavigableSet<E> subSet(E, E);
     method public java.util.NavigableSet<E> tailSet(E, boolean);
@@ -62068,8 +62623,11 @@
   public class CopyOnWriteArraySet extends java.util.AbstractSet implements java.io.Serializable {
     ctor public CopyOnWriteArraySet();
     ctor public CopyOnWriteArraySet(java.util.Collection<? extends E>);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public java.util.Iterator<E> iterator();
+    method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class CountDownLatch {
@@ -62080,6 +62638,32 @@
     method public long getCount();
   }
 
+  public abstract class CountedCompleter extends java.util.concurrent.ForkJoinTask {
+    ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>, int);
+    ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>);
+    ctor protected CountedCompleter();
+    method public final void addToPendingCount(int);
+    method public final boolean compareAndSetPendingCount(int, int);
+    method public void complete(T);
+    method public abstract void compute();
+    method public final int decrementPendingCountUnlessZero();
+    method protected final boolean exec();
+    method public final java.util.concurrent.CountedCompleter<?> firstComplete();
+    method public final java.util.concurrent.CountedCompleter<?> getCompleter();
+    method public final int getPendingCount();
+    method public T getRawResult();
+    method public final java.util.concurrent.CountedCompleter<?> getRoot();
+    method public final void helpComplete(int);
+    method public final java.util.concurrent.CountedCompleter<?> nextComplete();
+    method public void onCompletion(java.util.concurrent.CountedCompleter<?>);
+    method public boolean onExceptionalCompletion(java.lang.Throwable, java.util.concurrent.CountedCompleter<?>);
+    method public final void propagateCompletion();
+    method public final void quietlyCompleteRoot();
+    method public final void setPendingCount(int);
+    method protected void setRawResult(T);
+    method public final void tryComplete();
+  }
+
   public class CyclicBarrier {
     ctor public CyclicBarrier(int, java.lang.Runnable);
     ctor public CyclicBarrier(int);
@@ -62170,6 +62754,8 @@
     method public static java.util.concurrent.ExecutorService newSingleThreadExecutor(java.util.concurrent.ThreadFactory);
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor();
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory);
+    method public static java.util.concurrent.ExecutorService newWorkStealingPool(int);
+    method public static java.util.concurrent.ExecutorService newWorkStealingPool();
     method public static java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.ThreadFactory privilegedThreadFactory();
@@ -62183,11 +62769,13 @@
     ctor public ForkJoinPool(int, java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory, java.lang.Thread.UncaughtExceptionHandler, boolean);
     method public boolean awaitQuiescence(long, java.util.concurrent.TimeUnit);
     method public boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public static java.util.concurrent.ForkJoinPool commonPool();
     method protected int drainTasksTo(java.util.Collection<? super java.util.concurrent.ForkJoinTask<?>>);
     method public void execute(java.util.concurrent.ForkJoinTask<?>);
     method public void execute(java.lang.Runnable);
     method public int getActiveThreadCount();
     method public boolean getAsyncMode();
+    method public static int getCommonPoolParallelism();
     method public java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory getFactory();
     method public int getParallelism();
     method public int getPoolSize();
@@ -62225,6 +62813,7 @@
     method public static java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T);
     method public static java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>);
     method public boolean cancel(boolean);
+    method public final boolean compareAndSetForkJoinTaskTag(short, short);
     method public void complete(V);
     method public void completeExceptionally(java.lang.Throwable);
     method protected abstract boolean exec();
@@ -62232,6 +62821,7 @@
     method public final V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
     method public final V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
     method public final java.lang.Throwable getException();
+    method public final short getForkJoinTaskTag();
     method public static java.util.concurrent.ForkJoinPool getPool();
     method public static int getQueuedTaskCount();
     method public abstract V getRawResult();
@@ -62250,9 +62840,11 @@
     method protected static java.util.concurrent.ForkJoinTask<?> peekNextLocalTask();
     method protected static java.util.concurrent.ForkJoinTask<?> pollNextLocalTask();
     method protected static java.util.concurrent.ForkJoinTask<?> pollTask();
+    method public final void quietlyComplete();
     method public final void quietlyInvoke();
     method public final void quietlyJoin();
     method public void reinitialize();
+    method public final short setForkJoinTaskTag(short);
     method protected abstract void setRawResult(V);
     method public boolean tryUnfork();
   }
@@ -62326,6 +62918,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
     method public E takeFirst() throws java.lang.InterruptedException;
     method public E takeLast() throws java.lang.InterruptedException;
@@ -62346,6 +62939,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -62365,6 +62959,7 @@
     method public void put(E);
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
     method public void transfer(E) throws java.lang.InterruptedException;
     method public boolean tryTransfer(E);
@@ -62412,6 +63007,7 @@
     method public void put(E);
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -62515,6 +63111,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -62644,112 +63241,136 @@
   public class AtomicInteger extends java.lang.Number implements java.io.Serializable {
     ctor public AtomicInteger(int);
     ctor public AtomicInteger();
+    method public final int accumulateAndGet(int, java.util.function.IntBinaryOperator);
     method public final int addAndGet(int);
     method public final boolean compareAndSet(int, int);
     method public final int decrementAndGet();
     method public double doubleValue();
     method public float floatValue();
     method public final int get();
+    method public final int getAndAccumulate(int, java.util.function.IntBinaryOperator);
     method public final int getAndAdd(int);
     method public final int getAndDecrement();
     method public final int getAndIncrement();
     method public final int getAndSet(int);
+    method public final int getAndUpdate(java.util.function.IntUnaryOperator);
     method public final int incrementAndGet();
     method public int intValue();
     method public final void lazySet(int);
     method public long longValue();
     method public final void set(int);
+    method public final int updateAndGet(java.util.function.IntUnaryOperator);
     method public final boolean weakCompareAndSet(int, int);
   }
 
   public class AtomicIntegerArray implements java.io.Serializable {
     ctor public AtomicIntegerArray(int);
     ctor public AtomicIntegerArray(int[]);
+    method public final int accumulateAndGet(int, int, java.util.function.IntBinaryOperator);
     method public final int addAndGet(int, int);
     method public final boolean compareAndSet(int, int, int);
     method public final int decrementAndGet(int);
     method public final int get(int);
+    method public final int getAndAccumulate(int, int, java.util.function.IntBinaryOperator);
     method public final int getAndAdd(int, int);
     method public final int getAndDecrement(int);
     method public final int getAndIncrement(int);
     method public final int getAndSet(int, int);
+    method public final int getAndUpdate(int, java.util.function.IntUnaryOperator);
     method public final int incrementAndGet(int);
     method public final void lazySet(int, int);
     method public final int length();
     method public final void set(int, int);
+    method public final int updateAndGet(int, java.util.function.IntUnaryOperator);
     method public final boolean weakCompareAndSet(int, int, int);
   }
 
   public abstract class AtomicIntegerFieldUpdater {
     ctor protected AtomicIntegerFieldUpdater();
+    method public final int accumulateAndGet(T, int, java.util.function.IntBinaryOperator);
     method public int addAndGet(T, int);
     method public abstract boolean compareAndSet(T, int, int);
     method public int decrementAndGet(T);
     method public abstract int get(T);
+    method public final int getAndAccumulate(T, int, java.util.function.IntBinaryOperator);
     method public int getAndAdd(T, int);
     method public int getAndDecrement(T);
     method public int getAndIncrement(T);
     method public int getAndSet(T, int);
+    method public final int getAndUpdate(T, java.util.function.IntUnaryOperator);
     method public int incrementAndGet(T);
     method public abstract void lazySet(T, int);
     method public static java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, int);
+    method public final int updateAndGet(T, java.util.function.IntUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, int, int);
   }
 
   public class AtomicLong extends java.lang.Number implements java.io.Serializable {
     ctor public AtomicLong(long);
     ctor public AtomicLong();
+    method public final long accumulateAndGet(long, java.util.function.LongBinaryOperator);
     method public final long addAndGet(long);
     method public final boolean compareAndSet(long, long);
     method public final long decrementAndGet();
     method public double doubleValue();
     method public float floatValue();
     method public final long get();
+    method public final long getAndAccumulate(long, java.util.function.LongBinaryOperator);
     method public final long getAndAdd(long);
     method public final long getAndDecrement();
     method public final long getAndIncrement();
     method public final long getAndSet(long);
+    method public final long getAndUpdate(java.util.function.LongUnaryOperator);
     method public final long incrementAndGet();
     method public int intValue();
     method public final void lazySet(long);
     method public long longValue();
     method public final void set(long);
+    method public final long updateAndGet(java.util.function.LongUnaryOperator);
     method public final boolean weakCompareAndSet(long, long);
   }
 
   public class AtomicLongArray implements java.io.Serializable {
     ctor public AtomicLongArray(int);
     ctor public AtomicLongArray(long[]);
+    method public final long accumulateAndGet(int, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(int, long);
     method public final boolean compareAndSet(int, long, long);
     method public final long decrementAndGet(int);
     method public final long get(int);
+    method public final long getAndAccumulate(int, long, java.util.function.LongBinaryOperator);
     method public final long getAndAdd(int, long);
     method public final long getAndDecrement(int);
     method public final long getAndIncrement(int);
     method public final long getAndSet(int, long);
+    method public final long getAndUpdate(int, java.util.function.LongUnaryOperator);
     method public final long incrementAndGet(int);
     method public final void lazySet(int, long);
     method public final int length();
     method public final void set(int, long);
+    method public final long updateAndGet(int, java.util.function.LongUnaryOperator);
     method public final boolean weakCompareAndSet(int, long, long);
   }
 
   public abstract class AtomicLongFieldUpdater {
     ctor protected AtomicLongFieldUpdater();
+    method public final long accumulateAndGet(T, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(T, long);
     method public abstract boolean compareAndSet(T, long, long);
     method public long decrementAndGet(T);
     method public abstract long get(T);
+    method public final long getAndAccumulate(T, long, java.util.function.LongBinaryOperator);
     method public long getAndAdd(T, long);
     method public long getAndDecrement(T);
     method public long getAndIncrement(T);
     method public long getAndSet(T, long);
+    method public final long getAndUpdate(T, java.util.function.LongUnaryOperator);
     method public long incrementAndGet(T);
     method public abstract void lazySet(T, long);
     method public static java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, long);
+    method public final long updateAndGet(T, java.util.function.LongUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, long, long);
   }
 
@@ -62767,34 +63388,46 @@
   public class AtomicReference implements java.io.Serializable {
     ctor public AtomicReference(V);
     ctor public AtomicReference();
+    method public final V accumulateAndGet(V, java.util.function.BinaryOperator<V>);
     method public final boolean compareAndSet(V, V);
     method public final V get();
+    method public final V getAndAccumulate(V, java.util.function.BinaryOperator<V>);
     method public final V getAndSet(V);
+    method public final V getAndUpdate(java.util.function.UnaryOperator<V>);
     method public final void lazySet(V);
     method public final void set(V);
+    method public final V updateAndGet(java.util.function.UnaryOperator<V>);
     method public final boolean weakCompareAndSet(V, V);
   }
 
   public class AtomicReferenceArray implements java.io.Serializable {
     ctor public AtomicReferenceArray(int);
     ctor public AtomicReferenceArray(E[]);
+    method public final E accumulateAndGet(int, E, java.util.function.BinaryOperator<E>);
     method public final boolean compareAndSet(int, E, E);
     method public final E get(int);
+    method public final E getAndAccumulate(int, E, java.util.function.BinaryOperator<E>);
     method public final E getAndSet(int, E);
+    method public final E getAndUpdate(int, java.util.function.UnaryOperator<E>);
     method public final void lazySet(int, E);
     method public final int length();
     method public final void set(int, E);
+    method public final E updateAndGet(int, java.util.function.UnaryOperator<E>);
     method public final boolean weakCompareAndSet(int, E, E);
   }
 
   public abstract class AtomicReferenceFieldUpdater {
     ctor protected AtomicReferenceFieldUpdater();
+    method public final V accumulateAndGet(T, V, java.util.function.BinaryOperator<V>);
     method public abstract boolean compareAndSet(T, V, V);
     method public abstract V get(T);
+    method public final V getAndAccumulate(T, V, java.util.function.BinaryOperator<V>);
     method public V getAndSet(T, V);
+    method public final V getAndUpdate(T, java.util.function.UnaryOperator<V>);
     method public abstract void lazySet(T, V);
     method public static java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String);
     method public abstract void set(T, V);
+    method public final V updateAndGet(T, java.util.function.UnaryOperator<V>);
     method public abstract boolean weakCompareAndSet(T, V, V);
   }
 
@@ -62809,6 +63442,59 @@
     method public boolean weakCompareAndSet(V, V, int, int);
   }
 
+  public class DoubleAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public DoubleAccumulator(java.util.function.DoubleBinaryOperator, double);
+    method public void accumulate(double);
+    method public double doubleValue();
+    method public float floatValue();
+    method public double get();
+    method public double getThenReset();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+  }
+
+  public class DoubleAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public DoubleAdder();
+    method public void add(double);
+    method public double doubleValue();
+    method public float floatValue();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+    method public double sum();
+    method public double sumThenReset();
+  }
+
+  public class LongAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public LongAccumulator(java.util.function.LongBinaryOperator, long);
+    method public void accumulate(long);
+    method public double doubleValue();
+    method public float floatValue();
+    method public long get();
+    method public long getThenReset();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+  }
+
+  public class LongAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public LongAdder();
+    method public void add(long);
+    method public void decrement();
+    method public double doubleValue();
+    method public float floatValue();
+    method public void increment();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+    method public long sum();
+    method public long sumThenReset();
+  }
+
+   abstract class Striped64 extends java.lang.Number {
+  }
+
 }
 
 package java.util.concurrent.locks {
@@ -63016,6 +63702,34 @@
     method public void unlock();
   }
 
+  public class StampedLock implements java.io.Serializable {
+    ctor public StampedLock();
+    method public java.util.concurrent.locks.Lock asReadLock();
+    method public java.util.concurrent.locks.ReadWriteLock asReadWriteLock();
+    method public java.util.concurrent.locks.Lock asWriteLock();
+    method public int getReadLockCount();
+    method public boolean isReadLocked();
+    method public boolean isWriteLocked();
+    method public long readLock();
+    method public long readLockInterruptibly() throws java.lang.InterruptedException;
+    method public long tryConvertToOptimisticRead(long);
+    method public long tryConvertToReadLock(long);
+    method public long tryConvertToWriteLock(long);
+    method public long tryOptimisticRead();
+    method public long tryReadLock();
+    method public long tryReadLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public boolean tryUnlockRead();
+    method public boolean tryUnlockWrite();
+    method public long tryWriteLock();
+    method public long tryWriteLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public void unlock(long);
+    method public void unlockRead(long);
+    method public void unlockWrite(long);
+    method public boolean validate(long);
+    method public long writeLock();
+    method public long writeLockInterruptibly() throws java.lang.InterruptedException;
+  }
+
 }
 
 package java.util.function {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 79f7297..caeecf5 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -33,6 +33,25 @@
 
 }
 
+package android.graphics {
+
+  public deprecated class AvoidXfermode extends android.graphics.Xfermode {
+    ctor public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode);
+  }
+
+  public static final class AvoidXfermode.Mode extends java.lang.Enum {
+    method public static android.graphics.AvoidXfermode.Mode valueOf(java.lang.String);
+    method public static final android.graphics.AvoidXfermode.Mode[] values();
+    enum_constant public static final android.graphics.AvoidXfermode.Mode AVOID;
+    enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET;
+  }
+
+  public deprecated class PixelXorXfermode extends android.graphics.Xfermode {
+    ctor public PixelXorXfermode(int);
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 1f47f4c..3f37f5f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -559,6 +559,7 @@
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillColor = 16843780; // 0x1010404
     field public static final int fillEnabled = 16843343; // 0x101024f
+    field public static final int fillType = 16844064; // 0x1010520
     field public static final int fillViewport = 16843130; // 0x101017a
     field public static final int filter = 16843035; // 0x101011b
     field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -879,6 +880,7 @@
     field public static final int nextFocusLeft = 16842977; // 0x10100e1
     field public static final int nextFocusRight = 16842978; // 0x10100e2
     field public static final int nextFocusUp = 16842979; // 0x10100e3
+    field public static final int nfcAntennaPositionDrawable = 16844063; // 0x101051f
     field public static final int noHistory = 16843309; // 0x101022d
     field public static final int normalScreens = 16843397; // 0x1010285
     field public static final int notificationTimeout = 16843651; // 0x1010383
@@ -3441,7 +3443,7 @@
     method public android.view.View getCurrentFocus();
     method public android.app.FragmentManager getFragmentManager();
     method public android.content.Intent getIntent();
-    method public deprecated java.lang.Object getLastNonConfigurationInstance();
+    method public java.lang.Object getLastNonConfigurationInstance();
     method public android.view.LayoutInflater getLayoutInflater();
     method public android.app.LoaderManager getLoaderManager();
     method public java.lang.String getLocalClassName();
@@ -3535,14 +3537,13 @@
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public void onProvideAssistContent(android.app.assist.AssistContent);
     method public void onProvideAssistData(android.os.Bundle);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public android.net.Uri onProvideReferrer();
     method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
     method protected void onRestart();
     method protected void onRestoreInstanceState(android.os.Bundle);
     method public void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method protected void onResume();
-    method public deprecated java.lang.Object onRetainNonConfigurationInstance();
+    method public java.lang.Object onRetainNonConfigurationInstance();
     method protected void onSaveInstanceState(android.os.Bundle);
     method public void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -4217,7 +4218,6 @@
     method public void onPanelClosed(int, android.view.Menu);
     method public boolean onPrepareOptionsMenu(android.view.Menu);
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public void onRestoreInstanceState(android.os.Bundle);
     method public android.os.Bundle onSaveInstanceState();
     method public boolean onSearchRequested(android.view.SearchEvent);
@@ -5855,7 +5855,6 @@
     method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName);
     method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
-    method public boolean getDeviceLoggingEnabled(android.content.ComponentName);
     method public java.lang.String getDeviceOwnerLockScreenInfo();
     method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
@@ -5904,6 +5903,7 @@
     method public boolean isMasterVolumeMuted(android.content.ComponentName);
     method public boolean isProfileOwnerApp(java.lang.String);
     method public boolean isProvisioningAllowed(java.lang.String);
+    method public boolean isSecurityLoggingEnabled(android.content.ComponentName);
     method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String);
     method public void lockNow();
     method public void reboot(android.content.ComponentName);
@@ -5913,8 +5913,8 @@
     method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
     method public boolean requestBugreport(android.content.ComponentName);
     method public boolean resetPassword(java.lang.String, int);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrieveDeviceLogs(android.content.ComponentName);
-    method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrievePreviousDeviceLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName);
+    method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName);
     method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
     method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String);
     method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
@@ -5926,7 +5926,6 @@
     method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
     method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
     method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean);
-    method public void setDeviceLoggingEnabled(android.content.ComponentName, boolean);
     method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String);
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
@@ -5959,6 +5958,7 @@
     method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
     method public void setScreenCaptureDisabled(android.content.ComponentName, boolean);
     method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+    method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean);
     method public void setShortSupportMessage(android.content.ComponentName, java.lang.String);
     method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
@@ -5982,6 +5982,7 @@
     field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
     field public static final int ENCRYPTION_STATUS_ACTIVE = 3; // 0x3
     field public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4; // 0x4
+    field public static final int ENCRYPTION_STATUS_ACTIVE_PER_USER = 5; // 0x5
     field public static final int ENCRYPTION_STATUS_INACTIVE = 1; // 0x1
     field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0
     field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
@@ -6043,6 +6044,27 @@
     field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
   }
 
+  public class SecurityLog {
+    ctor public SecurityLog();
+    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
+    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
+    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
+    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
+    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
+    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
+    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
+    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
+  }
+
+  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.Object getData();
+    method public int getTag();
+    method public long getTimeNanos();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.admin.SecurityLog.SecurityEvent> CREATOR;
+  }
+
   public class SystemUpdatePolicy implements android.os.Parcelable {
     method public static android.app.admin.SystemUpdatePolicy createAutomaticInstallPolicy();
     method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy();
@@ -6375,8 +6397,8 @@
     method public long getTxPackets();
     method public int getUid();
     field public static final int ROAMING_ALL = -1; // 0xffffffff
-    field public static final int ROAMING_DEFAULT = 1; // 0x1
-    field public static final int ROAMING_ROAMING = 2; // 0x2
+    field public static final int ROAMING_NO = 1; // 0x1
+    field public static final int ROAMING_YES = 2; // 0x2
     field public static final int STATE_ALL = -1; // 0xffffffff
     field public static final int STATE_DEFAULT = 1; // 0x1
     field public static final int STATE_FOREGROUND = 2; // 0x2
@@ -6583,31 +6605,6 @@
 
 }
 
-package android.auditing {
-
-  public class SecurityLog {
-    ctor public SecurityLog();
-    field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
-    field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
-    field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
-    field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456
-    field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457
-    field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458
-    field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453
-    field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454
-  }
-
-  public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
-    method public int describeContents();
-    method public java.lang.Object getData();
-    method public int getTag();
-    method public long getTimeNanos();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.auditing.SecurityLog.SecurityEvent> CREATOR;
-  }
-
-}
-
 package android.bluetooth {
 
   public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
@@ -8118,7 +8115,7 @@
     field public static final java.lang.String DOWNLOAD_SERVICE = "download";
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
     field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
-    field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardwareproperties";
+    field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
     field public static final java.lang.String INPUT_SERVICE = "input";
     field public static final java.lang.String JOB_SCHEDULER_SERVICE = "jobscheduler";
@@ -8148,6 +8145,7 @@
     field public static final java.lang.String SENSOR_SERVICE = "sensor";
     field public static final java.lang.String SHORTCUT_SERVICE = "shortcut";
     field public static final java.lang.String STORAGE_SERVICE = "storage";
+    field public static final java.lang.String SYSTEM_HEALTH_SERVICE = "systemhealth";
     field public static final java.lang.String TELECOM_SERVICE = "telecom";
     field public static final java.lang.String TELEPHONY_SERVICE = "phone";
     field public static final java.lang.String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
@@ -9334,6 +9332,7 @@
     field public int flags;
     field public int largestWidthLimitDp;
     field public java.lang.String manageSpaceActivityName;
+    field public java.lang.String minSdkVersion;
     field public java.lang.String nativeLibraryDir;
     field public java.lang.String permission;
     field public java.lang.String processName;
@@ -9459,6 +9458,7 @@
     method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
     method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
+    method public boolean hasShortcutHostPermission();
     method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
     method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
     method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle);
@@ -9569,6 +9569,7 @@
     method public java.lang.String[] getNames() throws java.io.IOException;
     method public java.io.InputStream openRead(java.lang.String) throws java.io.IOException;
     method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
+    method public void removeSplit(java.lang.String) throws java.io.IOException;
     method public void setStagingProgress(float);
   }
 
@@ -10004,6 +10005,7 @@
     method public int getWeight();
     method public boolean hasIconFile();
     method public boolean hasIconResource();
+    method public boolean hasKeyFieldsOnly();
     method public boolean isDynamic();
     method public boolean isPinned();
     method public void writeToParcel(android.os.Parcel, int);
@@ -10014,6 +10016,7 @@
     field public static final int FLAG_DYNAMIC = 1; // 0x1
     field public static final int FLAG_HAS_ICON_FILE = 8; // 0x8
     field public static final int FLAG_HAS_ICON_RES = 4; // 0x4
+    field public static final int FLAG_KEY_FIELDS_ONLY = 16; // 0x10
     field public static final int FLAG_PINNED = 2; // 0x2
   }
 
@@ -10034,6 +10037,7 @@
     method public void deleteAllDynamicShortcuts();
     method public void deleteDynamicShortcut(java.lang.String);
     method public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
+    method public int getIconMaxDimensions();
     method public int getMaxDynamicShortcutCount();
     method public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
     method public long getRateLimitResetTime();
@@ -10118,7 +10122,6 @@
     method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
-    method public int getChangingConfigurations();
     method public int getColorForState(int[], int);
     method public int getDefaultColor();
     method public boolean isOpaque();
@@ -10130,6 +10133,7 @@
 
   public abstract class ComplexColor {
     ctor public ComplexColor();
+    method public int getChangingConfigurations();
     method public abstract int getDefaultColor();
     method public boolean isStateful();
   }
@@ -11477,17 +11481,6 @@
 
 package android.graphics {
 
-  public deprecated class AvoidXfermode extends android.graphics.Xfermode {
-    ctor public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode);
-  }
-
-  public static final class AvoidXfermode.Mode extends java.lang.Enum {
-    method public static android.graphics.AvoidXfermode.Mode valueOf(java.lang.String);
-    method public static final android.graphics.AvoidXfermode.Mode[] values();
-    enum_constant public static final android.graphics.AvoidXfermode.Mode AVOID;
-    enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET;
-  }
-
   public final class Bitmap implements android.os.Parcelable {
     method public boolean compress(android.graphics.Bitmap.CompressFormat, int, java.io.OutputStream);
     method public android.graphics.Bitmap copy(android.graphics.Bitmap.Config, boolean);
@@ -12354,10 +12347,6 @@
     field public int bytesPerPixel;
   }
 
-  public deprecated class PixelXorXfermode extends android.graphics.Xfermode {
-    ctor public PixelXorXfermode(int);
-  }
-
   public class Point implements android.os.Parcelable {
     ctor public Point();
     ctor public Point(int, int);
@@ -12917,7 +12906,8 @@
     method public int getGradientType();
     method public int getOpacity();
     method public android.graphics.drawable.GradientDrawable.Orientation getOrientation();
-    method public boolean isUseLevel();
+    method public int getShape();
+    method public boolean getUseLevel();
     method public void setAlpha(int);
     method public void setColor(int);
     method public void setColor(android.content.res.ColorStateList);
@@ -13036,9 +13026,9 @@
     method public void setPaddingMode(int);
     method public void setPaddingRelative(int, int, int, int);
     method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
+    field public static final int INSET_UNDEFINED = -2147483648; // 0x80000000
     field public static final int PADDING_MODE_NEST = 0; // 0x0
     field public static final int PADDING_MODE_STACK = 1; // 0x1
-    field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000
   }
 
   public class LevelListDrawable extends android.graphics.drawable.DrawableContainer {
@@ -13779,6 +13769,7 @@
 
   public static abstract class CameraCaptureSession.CaptureCallback {
     ctor public CameraCaptureSession.CaptureCallback();
+    method public void onCaptureBufferLost(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.view.Surface, long);
     method public void onCaptureCompleted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult);
     method public void onCaptureFailed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureFailure);
     method public void onCaptureProgressed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
@@ -19235,6 +19226,7 @@
   }
 
   public final class GnssClock implements android.os.Parcelable {
+    ctor public GnssClock();
     method public int describeContents();
     method public double getBiasNanos();
     method public double getBiasUncertaintyNanos();
@@ -19275,6 +19267,7 @@
   }
 
   public final class GnssMeasurement implements android.os.Parcelable {
+    ctor public GnssMeasurement();
     method public int describeContents();
     method public double getAccumulatedDeltaRangeMeters();
     method public int getAccumulatedDeltaRangeState();
@@ -19317,6 +19310,7 @@
     method public void setCn0DbHz(double);
     method public void setConstellationType(int);
     method public void setMultipathIndicator(int);
+    method public void setPseudorangeRateCorrected(boolean);
     method public void setPseudorangeRateMetersPerSecond(double);
     method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
     method public void setReceivedSvTimeNanos(long);
@@ -19367,6 +19361,7 @@
   }
 
   public final class GnssNavigationMessage implements android.os.Parcelable {
+    ctor public GnssNavigationMessage();
     method public int describeContents();
     method public byte[] getData();
     method public int getMessageId();
@@ -20238,37 +20233,129 @@
     field public static final int ORIENTATION_TRANSVERSE = 7; // 0x7
     field public static final int ORIENTATION_UNDEFINED = 0; // 0x0
     field public static final java.lang.String TAG_APERTURE = "FNumber";
+    field public static final java.lang.String TAG_APERTURE_VALUE = "ApertureValue";
+    field public static final java.lang.String TAG_ARTIST = "Artist";
+    field public static final java.lang.String TAG_BITS_PER_SAMPLE = "BitsPerSample";
+    field public static final java.lang.String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
+    field public static final java.lang.String TAG_CFA_PATTERN = "CFAPattern";
+    field public static final java.lang.String TAG_COLOR_SPACE = "ColorSpace";
+    field public static final java.lang.String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
+    field public static final java.lang.String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
+    field public static final java.lang.String TAG_COMPRESSION = "Compression";
+    field public static final java.lang.String TAG_CONTRAST = "Contrast";
+    field public static final java.lang.String TAG_COPYRIGHT = "Copyright";
+    field public static final java.lang.String TAG_CUSTOM_RENDERED = "CustomRendered";
     field public static final java.lang.String TAG_DATETIME = "DateTime";
     field public static final java.lang.String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    field public static final java.lang.String TAG_DATETIME_ORIGINAL = "DateTimeOriginal";
+    field public static final java.lang.String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription";
     field public static final java.lang.String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+    field public static final java.lang.String TAG_EXIF_VERSION = "ExifVersion";
     field public static final java.lang.String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+    field public static final java.lang.String TAG_EXPOSURE_INDEX = "ExposureIndex";
     field public static final java.lang.String TAG_EXPOSURE_MODE = "ExposureMode";
     field public static final java.lang.String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
     field public static final java.lang.String TAG_EXPOSURE_TIME = "ExposureTime";
+    field public static final java.lang.String TAG_FILE_SOURCE = "FileSource";
     field public static final java.lang.String TAG_FLASH = "Flash";
+    field public static final java.lang.String TAG_FLASHPIX_VERSION = "FlashpixVersion";
+    field public static final java.lang.String TAG_FLASH_ENERGY = "FlashEnergy";
     field public static final java.lang.String TAG_FOCAL_LENGTH = "FocalLength";
+    field public static final java.lang.String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm";
+    field public static final java.lang.String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit";
+    field public static final java.lang.String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution";
+    field public static final java.lang.String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
+    field public static final java.lang.String TAG_F_NUMBER = "FNumber";
+    field public static final java.lang.String TAG_GAIN_CONTROL = "GainControl";
     field public static final java.lang.String TAG_GPS_ALTITUDE = "GPSAltitude";
     field public static final java.lang.String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
+    field public static final java.lang.String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
     field public static final java.lang.String TAG_GPS_DATESTAMP = "GPSDateStamp";
+    field public static final java.lang.String TAG_GPS_DEST_BEARING = "GPSDestBearing";
+    field public static final java.lang.String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef";
+    field public static final java.lang.String TAG_GPS_DEST_DISTANCE = "GPSDestDistance";
+    field public static final java.lang.String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef";
+    field public static final java.lang.String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude";
+    field public static final java.lang.String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef";
+    field public static final java.lang.String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude";
+    field public static final java.lang.String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
+    field public static final java.lang.String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
+    field public static final java.lang.String TAG_GPS_DOP = "GPSDOP";
+    field public static final java.lang.String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
+    field public static final java.lang.String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
     field public static final java.lang.String TAG_GPS_LATITUDE = "GPSLatitude";
     field public static final java.lang.String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
     field public static final java.lang.String TAG_GPS_LONGITUDE = "GPSLongitude";
     field public static final java.lang.String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    field public static final java.lang.String TAG_GPS_MAP_DATUM = "GPSMapDatum";
+    field public static final java.lang.String TAG_GPS_MEASURE_MODE = "GPSMeasureMode";
     field public static final java.lang.String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
+    field public static final java.lang.String TAG_GPS_SATELLITES = "GPSSatellites";
+    field public static final java.lang.String TAG_GPS_SPEED = "GPSSpeed";
+    field public static final java.lang.String TAG_GPS_SPEED_REF = "GPSSpeedRef";
+    field public static final java.lang.String TAG_GPS_STATUS = "GPSStatus";
     field public static final java.lang.String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+    field public static final java.lang.String TAG_GPS_TRACK = "GPSTrack";
+    field public static final java.lang.String TAG_GPS_TRACK_REF = "GPSTrackRef";
+    field public static final java.lang.String TAG_GPS_VERSION_ID = "GPSVersionID";
+    field public static final java.lang.String TAG_IMAGE_DESCRIPTION = "ImageDescription";
     field public static final java.lang.String TAG_IMAGE_LENGTH = "ImageLength";
+    field public static final java.lang.String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
     field public static final java.lang.String TAG_IMAGE_WIDTH = "ImageWidth";
+    field public static final java.lang.String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
     field public static final java.lang.String TAG_ISO = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
+    field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
     field public static final java.lang.String TAG_LIGHT_SOURCE = "LightSource";
     field public static final java.lang.String TAG_MAKE = "Make";
+    field public static final java.lang.String TAG_MAKER_NOTE = "MakerNote";
+    field public static final java.lang.String TAG_MAX_APERTURE_VALUE = "MaxApertureValue";
     field public static final java.lang.String TAG_METERING_MODE = "MeteringMode";
     field public static final java.lang.String TAG_MODEL = "Model";
+    field public static final java.lang.String TAG_OECF = "OECF";
     field public static final java.lang.String TAG_ORIENTATION = "Orientation";
+    field public static final java.lang.String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
+    field public static final java.lang.String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
+    field public static final java.lang.String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
+    field public static final java.lang.String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
+    field public static final java.lang.String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
+    field public static final java.lang.String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
+    field public static final java.lang.String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
+    field public static final java.lang.String TAG_RESOLUTION_UNIT = "ResolutionUnit";
+    field public static final java.lang.String TAG_ROWS_PER_STRIP = "RowsPerStrip";
+    field public static final java.lang.String TAG_SAMPLES_PER_PIXEL = "SamplesPerPixel";
+    field public static final java.lang.String TAG_SATURATION = "Saturation";
+    field public static final java.lang.String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
+    field public static final java.lang.String TAG_SCENE_TYPE = "SceneType";
+    field public static final java.lang.String TAG_SENSING_METHOD = "SensingMethod";
+    field public static final java.lang.String TAG_SHARPNESS = "Sharpness";
+    field public static final java.lang.String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
+    field public static final java.lang.String TAG_SOFTWARE = "Software";
+    field public static final java.lang.String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
+    field public static final java.lang.String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
+    field public static final java.lang.String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
+    field public static final java.lang.String TAG_STRIP_OFFSETS = "StripOffsets";
+    field public static final java.lang.String TAG_SUBJECT_AREA = "SubjectArea";
     field public static final java.lang.String TAG_SUBJECT_DISTANCE = "SubjectDistance";
+    field public static final java.lang.String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange";
+    field public static final java.lang.String TAG_SUBJECT_LOCATION = "SubjectLocation";
     field public static final java.lang.String TAG_SUBSEC_TIME = "SubSecTime";
     field public static final java.lang.String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
+    field public static final java.lang.String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized";
     field public static final java.lang.String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
+    field public static final java.lang.String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
+    field public static final java.lang.String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
+    field public static final java.lang.String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
+    field public static final java.lang.String TAG_TRANSFER_FUNCTION = "TransferFunction";
+    field public static final java.lang.String TAG_USER_COMMENT = "UserComment";
     field public static final java.lang.String TAG_WHITE_BALANCE = "WhiteBalance";
+    field public static final java.lang.String TAG_WHITE_POINT = "WhitePoint";
+    field public static final java.lang.String TAG_X_RESOLUTION = "XResolution";
+    field public static final java.lang.String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients";
+    field public static final java.lang.String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
+    field public static final java.lang.String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
+    field public static final java.lang.String TAG_Y_RESOLUTION = "YResolution";
     field public static final int WHITEBALANCE_AUTO = 0; // 0x0
     field public static final int WHITEBALANCE_MANUAL = 1; // 0x1
   }
@@ -20994,6 +21081,7 @@
     field public static final java.lang.String KEY_DURATION = "durationUs";
     field public static final java.lang.String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
     field public static final java.lang.String KEY_FRAME_RATE = "frame-rate";
+    field public static final java.lang.String KEY_HDR_STATIC_INFO = "hdr-static-info";
     field public static final java.lang.String KEY_HEIGHT = "height";
     field public static final java.lang.String KEY_INTRA_REFRESH_PERIOD = "intra-refresh-period";
     field public static final java.lang.String KEY_IS_ADTS = "is-adts";
@@ -23063,6 +23151,7 @@
     method public void notifyError(int);
     method public void notifyRecordingStopped(android.net.Uri);
     method public void notifyTuned(android.net.Uri);
+    method public void onAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public abstract void onRelease();
     method public abstract void onStartRecording(android.net.Uri);
     method public abstract void onStopRecording();
@@ -23080,6 +23169,7 @@
     method public void notifyTracksChanged(java.util.List<android.media.tv.TvTrackInfo>);
     method public void notifyVideoAvailable();
     method public void notifyVideoUnavailable(int);
+    method public void onAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public android.view.View onCreateOverlayView();
     method public boolean onGenericMotionEvent(android.view.MotionEvent);
     method public boolean onKeyDown(int, android.view.KeyEvent);
@@ -23111,6 +23201,7 @@
   public class TvRecordingClient {
     ctor public TvRecordingClient(android.content.Context, java.lang.String, android.media.tv.TvRecordingClient.RecordingCallback, android.os.Handler);
     method public void release();
+    method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public void startRecording(android.net.Uri);
     method public void stopRecording();
     method public void tune(java.lang.String, android.net.Uri);
@@ -23172,6 +23263,7 @@
     method public boolean onUnhandledInputEvent(android.view.InputEvent);
     method public void reset();
     method public void selectTrack(int, java.lang.String);
+    method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle);
     method public void setCallback(android.media.tv.TvView.TvInputCallback);
     method public void setCaptionEnabled(boolean);
     method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener);
@@ -29091,7 +29183,6 @@
     ctor public PersistableBundle();
     ctor public PersistableBundle(int);
     ctor public PersistableBundle(android.os.PersistableBundle);
-    ctor public PersistableBundle(android.os.Bundle);
     method public java.lang.Object clone();
     method public int describeContents();
     method public android.os.PersistableBundle getPersistableBundle(java.lang.String);
@@ -29421,6 +29512,147 @@
 
 }
 
+package android.os.health {
+
+  public class HealthStats {
+    method public java.lang.String getDataType();
+    method public long getMeasurement(int);
+    method public int getMeasurementKeyAt(int);
+    method public int getMeasurementKeyCount();
+    method public java.util.Map<java.lang.String, java.lang.Long> getMeasurements(int);
+    method public int getMeasurementsKeyAt(int);
+    method public int getMeasurementsKeyCount();
+    method public java.util.Map<java.lang.String, android.os.health.HealthStats> getStats(int);
+    method public int getStatsKeyAt(int);
+    method public int getStatsKeyCount();
+    method public android.os.health.TimerStat getTimer(int);
+    method public int getTimerCount(int);
+    method public int getTimerKeyAt(int);
+    method public int getTimerKeyCount();
+    method public long getTimerTime(int);
+    method public java.util.Map<java.lang.String, android.os.health.TimerStat> getTimers(int);
+    method public int getTimersKeyAt(int);
+    method public int getTimersKeyCount();
+    method public boolean hasMeasurement(int);
+    method public boolean hasMeasurements(int);
+    method public boolean hasStats(int);
+    method public boolean hasTimer(int);
+    method public boolean hasTimers(int);
+  }
+
+  public final class PackageHealthStats {
+    field public static final int MEASUREMENTS_WAKEUP_ALARMS_COUNT = 40002; // 0x9c42
+    field public static final int STATS_SERVICES = 40001; // 0x9c41
+  }
+
+  public final class PidHealthStats {
+    field public static final int MEASUREMENT_WAKE_NESTING_COUNT = 20001; // 0x4e21
+    field public static final int MEASUREMENT_WAKE_START_MS = 20003; // 0x4e23
+    field public static final int MEASUREMENT_WAKE_SUM_MS = 20002; // 0x4e22
+  }
+
+  public final class ProcessHealthStats {
+    field public static final int MEASUREMENT_ANR_COUNT = 30005; // 0x7535
+    field public static final int MEASUREMENT_CRASHES_COUNT = 30004; // 0x7534
+    field public static final int MEASUREMENT_FOREGROUND_MS = 30006; // 0x7536
+    field public static final int MEASUREMENT_STARTS_COUNT = 30003; // 0x7533
+    field public static final int MEASUREMENT_SYSTEM_TIME_MS = 30002; // 0x7532
+    field public static final int MEASUREMENT_USER_TIME_MS = 30001; // 0x7531
+  }
+
+  public final class ServiceHealthStats {
+    field public static final int MEASUREMENT_LAUNCH_COUNT = 50002; // 0xc352
+    field public static final int MEASUREMENT_START_SERVICE_COUNT = 50001; // 0xc351
+  }
+
+  public class SystemHealthManager {
+    method public static android.os.health.SystemHealthManager from(android.content.Context);
+    method public android.os.health.HealthStats takeMyUidSnapshot();
+    method public android.os.health.HealthStats takeUidSnapshot(int);
+    method public android.os.health.HealthStats[] takeUidSnapshots(int[]);
+  }
+
+  public class TimerStat implements android.os.Parcelable {
+    ctor public TimerStat();
+    ctor public TimerStat(int, long);
+    ctor public TimerStat(android.os.Parcel);
+    method public int describeContents();
+    method public int getCount();
+    method public long getTime();
+    method public void setCount(int);
+    method public void setTime(long);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.os.health.TimerStat> CREATOR;
+  }
+
+  public final class UidHealthStats {
+    field public static final int MEASUREMENT_BLUETOOTH_IDLE_MS = 10020; // 0x2724
+    field public static final int MEASUREMENT_BLUETOOTH_POWER_MAMS = 10023; // 0x2727
+    field public static final int MEASUREMENT_BLUETOOTH_RX_BYTES = 10052; // 0x2744
+    field public static final int MEASUREMENT_BLUETOOTH_RX_MS = 10021; // 0x2725
+    field public static final int MEASUREMENT_BLUETOOTH_RX_PACKETS = 10058; // 0x274a
+    field public static final int MEASUREMENT_BLUETOOTH_TX_BYTES = 10053; // 0x2745
+    field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
+    field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
+    field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
+    field public static final int MEASUREMENT_CPU_POWER_MAUS = 10064; // 0x2750
+    field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
+    field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
+    field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
+    field public static final int MEASUREMENT_MOBILE_RX_MS = 10025; // 0x2729
+    field public static final int MEASUREMENT_MOBILE_RX_PACKETS = 10054; // 0x2746
+    field public static final int MEASUREMENT_MOBILE_TX_BYTES = 10049; // 0x2741
+    field public static final int MEASUREMENT_MOBILE_TX_MS = 10026; // 0x272a
+    field public static final int MEASUREMENT_MOBILE_TX_PACKETS = 10055; // 0x2747
+    field public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = 10045; // 0x273d
+    field public static final int MEASUREMENT_REALTIME_BATTERY_MS = 10001; // 0x2711
+    field public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = 10003; // 0x2713
+    field public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = 10063; // 0x274f
+    field public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = 10047; // 0x273f
+    field public static final int MEASUREMENT_UPTIME_BATTERY_MS = 10002; // 0x2712
+    field public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = 10004; // 0x2714
+    field public static final int MEASUREMENT_USER_CPU_TIME_US = 10062; // 0x274e
+    field public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = 10029; // 0x272d
+    field public static final int MEASUREMENT_WIFI_IDLE_MS = 10016; // 0x2720
+    field public static final int MEASUREMENT_WIFI_MULTICAST_MS = 10031; // 0x272f
+    field public static final int MEASUREMENT_WIFI_POWER_MAMS = 10019; // 0x2723
+    field public static final int MEASUREMENT_WIFI_RUNNING_MS = 10028; // 0x272c
+    field public static final int MEASUREMENT_WIFI_RX_BYTES = 10050; // 0x2742
+    field public static final int MEASUREMENT_WIFI_RX_MS = 10017; // 0x2721
+    field public static final int MEASUREMENT_WIFI_RX_PACKETS = 10056; // 0x2748
+    field public static final int MEASUREMENT_WIFI_TX_BYTES = 10051; // 0x2743
+    field public static final int MEASUREMENT_WIFI_TX_MS = 10018; // 0x2722
+    field public static final int MEASUREMENT_WIFI_TX_PACKETS = 10057; // 0x2749
+    field public static final int STATS_PACKAGES = 10015; // 0x271f
+    field public static final int STATS_PIDS = 10013; // 0x271d
+    field public static final int STATS_PROCESSES = 10014; // 0x271e
+    field public static final int TIMERS_JOBS = 10010; // 0x271a
+    field public static final int TIMERS_SENSORS = 10012; // 0x271c
+    field public static final int TIMERS_SYNCS = 10009; // 0x2719
+    field public static final int TIMERS_WAKELOCKS_DRAW = 10008; // 0x2718
+    field public static final int TIMERS_WAKELOCKS_FULL = 10005; // 0x2715
+    field public static final int TIMERS_WAKELOCKS_PARTIAL = 10006; // 0x2716
+    field public static final int TIMERS_WAKELOCKS_WINDOW = 10007; // 0x2717
+    field public static final int TIMER_AUDIO = 10032; // 0x2730
+    field public static final int TIMER_BLUETOOTH_SCAN = 10037; // 0x2735
+    field public static final int TIMER_CAMERA = 10035; // 0x2733
+    field public static final int TIMER_FLASHLIGHT = 10034; // 0x2732
+    field public static final int TIMER_FOREGROUND_ACTIVITY = 10036; // 0x2734
+    field public static final int TIMER_GPS_SENSOR = 10011; // 0x271b
+    field public static final int TIMER_MOBILE_RADIO_ACTIVE = 10061; // 0x274d
+    field public static final int TIMER_PROCESS_STATE_BACKGROUND_MS = 10042; // 0x273a
+    field public static final int TIMER_PROCESS_STATE_CACHED_MS = 10043; // 0x273b
+    field public static final int TIMER_PROCESS_STATE_FOREGROUND_MS = 10041; // 0x2739
+    field public static final int TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS = 10039; // 0x2737
+    field public static final int TIMER_PROCESS_STATE_TOP_MS = 10038; // 0x2736
+    field public static final int TIMER_PROCESS_STATE_TOP_SLEEPING_MS = 10040; // 0x2738
+    field public static final int TIMER_VIBRATOR = 10044; // 0x273c
+    field public static final int TIMER_VIDEO = 10033; // 0x2731
+    field public static final int TIMER_WIFI_SCAN = 10030; // 0x272e
+  }
+
+}
+
 package android.os.storage {
 
   public abstract class OnObbStateChangeListener {
@@ -30585,6 +30817,7 @@
   public static class CallLog.Calls implements android.provider.BaseColumns {
     ctor public CallLog.Calls();
     method public static java.lang.String getLastOutgoingCall(android.content.Context);
+    field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7
     field public static final int BLOCKED_TYPE = 6; // 0x6
     field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number";
     field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri";
@@ -30607,6 +30840,7 @@
     field public static final java.lang.String DURATION = "duration";
     field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER";
     field public static final java.lang.String FEATURES = "features";
+    field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2
     field public static final int FEATURES_VIDEO = 1; // 0x1
     field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location";
     field public static final int INCOMING_TYPE = 1; // 0x1
@@ -32250,7 +32484,6 @@
     field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS";
     field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS";
     field public static final java.lang.String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
-    field public static final java.lang.String ACTION_SCREEN_READER_TUTORIAL = "android.settings.SCREEN_READER_TUTORIAL";
     field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
     field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS";
     field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";
@@ -35883,9 +36116,11 @@
     method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
+    method public void pullExternalCall();
     method public void registerCallback(android.telecom.Call.Callback);
     method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
     method public void reject(boolean, java.lang.String);
+    method public void sendCallEvent(java.lang.String, android.os.Bundle);
     method public void splitFromConference();
     method public void stopDtmfTone();
     method public void swapConference();
@@ -35899,6 +36134,7 @@
     field public static final int STATE_DISCONNECTING = 10; // 0xa
     field public static final int STATE_HOLDING = 3; // 0x3
     field public static final int STATE_NEW = 0; // 0x0
+    field public static final int STATE_PULLING_CALL = 11; // 0xb
     field public static final int STATE_RINGING = 2; // 0x2
     field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8
   }
@@ -35909,6 +36145,7 @@
     method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List<java.lang.String>);
     method public void onChildrenChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
     method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>);
+    method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
     method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
     method public void onParentChanged(android.telecom.Call, android.telecom.Call);
     method public void onPostDialWait(android.telecom.Call, java.lang.String);
@@ -35939,6 +36176,7 @@
     method public static java.lang.String propertiesToString(int);
     field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+    field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
@@ -35958,6 +36196,7 @@
     field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4
     field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
     field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
+    field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
     field public static final int PROPERTY_WIFI = 8; // 0x8
     field public static final int PROPERTY_WORK_CALL = 32; // 0x20
   }
@@ -36072,15 +36311,19 @@
     method public void onAnswer(int);
     method public void onAnswer();
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
+    method public void onCallEvent(java.lang.String, android.os.Bundle);
     method public void onDisconnect();
     method public void onHold();
     method public void onPlayDtmfTone(char);
     method public void onPostDialContinue(boolean);
+    method public void onPullExternalCall();
     method public void onReject();
+    method public void onReject(java.lang.String);
     method public void onSeparate();
     method public void onStateChanged(int);
     method public void onStopDtmfTone();
     method public void onUnhold();
+    method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
     method public final void setActive();
     method public final void setAddress(android.net.Uri, int);
     method public final void setAudioModeIsVoip(boolean);
@@ -36104,9 +36347,12 @@
     method public static java.lang.String stateToString(int);
     field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
+    field public static final int CAPABILITY_CAN_PULL_CALL = 33554432; // 0x2000000
+    field public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 4194304; // 0x400000
     field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
     field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
     field public static final int CAPABILITY_HOLD = 1; // 0x1
+    field public static final int CAPABILITY_IS_EXTERNAL_CALL = 16777216; // 0x1000000
     field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
     field public static final int CAPABILITY_MERGE_CONFERENCE = 4; // 0x4
     field public static final int CAPABILITY_MUTE = 64; // 0x40
@@ -36120,6 +36366,7 @@
     field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800
     field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2
     field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
+    field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
     field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
     field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
     field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -36129,6 +36376,7 @@
     field public static final int STATE_HOLDING = 5; // 0x5
     field public static final int STATE_INITIALIZING = 0; // 0x0
     field public static final int STATE_NEW = 1; // 0x1
+    field public static final int STATE_PULLING_CALL = 7; // 0x7
     field public static final int STATE_RINGING = 2; // 0x2
   }
 
@@ -36206,7 +36454,9 @@
     method public java.lang.String getReason();
     method public int getTone();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ANSWERED_ELSEWHERE = 11; // 0xb
     field public static final int BUSY = 7; // 0x7
+    field public static final int CALL_PULLED = 12; // 0xc
     field public static final int CANCELED = 4; // 0x4
     field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa
     field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR;
@@ -36242,6 +36492,7 @@
     method public void onCallAudioStateChanged(android.telecom.CallAudioState);
     method public void onCallRemoved(android.telecom.Call);
     method public void onCanAddCallChanged(boolean);
+    method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle);
     method public void onSilenceRinger();
     method public final void setAudioRoute(int);
     method public final void setMuted(boolean);
@@ -36392,6 +36643,7 @@
     method public boolean isVoipAudioMode();
     method public void playDtmfTone(char);
     method public void postDialContinue(boolean);
+    method public void pullExternalCall();
     method public void registerCallback(android.telecom.RemoteConnection.Callback);
     method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler);
     method public void reject();
@@ -36408,6 +36660,7 @@
     method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference);
     method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List<android.telecom.RemoteConnection>);
     method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int);
+    method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle);
     method public void onDestroyed(android.telecom.RemoteConnection);
     method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause);
     method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle);
@@ -36505,6 +36758,7 @@
     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 java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING";
     field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -36646,6 +36900,7 @@
     field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
     field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
     field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
+    field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
     field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
     field public static final java.lang.String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
     field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
@@ -42412,6 +42667,7 @@
     method public void onStartTemporaryDetach();
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
+    method public void onVisibilityAggregated(boolean);
     method protected void onVisibilityChanged(android.view.View, int);
     method public void onWindowFocusChanged(boolean);
     method public void onWindowSystemUiVisibilityChanged(int);
@@ -43508,7 +43764,7 @@
     method public abstract boolean onMenuOpened(int, android.view.Menu);
     method public abstract void onPanelClosed(int, android.view.Menu);
     method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
-    method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
+    method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
     method public abstract boolean onSearchRequested();
     method public abstract boolean onSearchRequested(android.view.SearchEvent);
     method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
@@ -50739,6 +50995,7 @@
   public abstract interface Iterable {
     method public default void forEach(java.util.function.Consumer<? super T>);
     method public abstract java.util.Iterator<T> iterator();
+    method public default java.util.Spliterator<T> spliterator();
   }
 
   public class LinkageError extends java.lang.Error {
@@ -57159,6 +57416,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class ArrayList extends java.util.AbstractList implements java.lang.Cloneable java.util.List java.util.RandomAccess java.io.Serializable {
@@ -57169,7 +57427,9 @@
     method public void ensureCapacity(int);
     method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
+    method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public void trimToSize();
   }
 
@@ -57252,6 +57512,24 @@
     method public static int hashCode(float[]);
     method public static int hashCode(double[]);
     method public static int hashCode(java.lang.Object[]);
+    method public static void parallelSort(byte[]);
+    method public static void parallelSort(byte[], int, int);
+    method public static void parallelSort(char[]);
+    method public static void parallelSort(char[], int, int);
+    method public static void parallelSort(short[]);
+    method public static void parallelSort(short[], int, int);
+    method public static void parallelSort(int[]);
+    method public static void parallelSort(int[], int, int);
+    method public static void parallelSort(long[]);
+    method public static void parallelSort(long[], int, int);
+    method public static void parallelSort(float[]);
+    method public static void parallelSort(float[], int, int);
+    method public static void parallelSort(double[]);
+    method public static void parallelSort(double[], int, int);
+    method public static void parallelSort(T[]);
+    method public static void parallelSort(T[], int, int);
+    method public static void parallelSort(T[], java.util.Comparator<? super T>);
+    method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>);
     method public static void sort(int[]);
     method public static void sort(int[], int, int);
     method public static void sort(long[]);
@@ -57270,6 +57548,14 @@
     method public static void sort(java.lang.Object[], int, int);
     method public static void sort(T[], java.util.Comparator<? super T>);
     method public static void sort(T[], int, int, java.util.Comparator<? super T>);
+    method public static java.util.Spliterator<T> spliterator(T[]);
+    method public static java.util.Spliterator<T> spliterator(T[], int, int);
+    method public static java.util.Spliterator.OfInt spliterator(int[]);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int, int);
+    method public static java.util.Spliterator.OfLong spliterator(long[]);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int, int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[]);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int, int);
     method public static java.lang.String toString(long[]);
     method public static java.lang.String toString(int[]);
     method public static java.lang.String toString(short[]);
@@ -57431,6 +57717,7 @@
     method public abstract java.util.Iterator<E> iterator();
     method public abstract boolean remove(java.lang.Object);
     method public abstract boolean removeAll(java.util.Collection<?>);
+    method public default boolean removeIf(java.util.function.Predicate<? super E>);
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract int size();
     method public abstract java.lang.Object[] toArray();
@@ -57769,6 +58056,7 @@
     method public java.lang.Object clone();
     method public java.util.Iterator<E> iterator();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class Hashtable extends java.util.Dictionary implements java.lang.Cloneable java.util.Map java.io.Serializable {
@@ -57913,6 +58201,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public abstract interface List implements java.util.Collection {
@@ -58062,23 +58351,37 @@
 
   public abstract interface Map {
     method public abstract void clear();
+    method public default V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public default V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public default V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public abstract boolean containsKey(java.lang.Object);
     method public abstract boolean containsValue(java.lang.Object);
     method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public abstract boolean equals(java.lang.Object);
     method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public abstract V get(java.lang.Object);
+    method public default V getOrDefault(java.lang.Object, V);
     method public abstract int hashCode();
     method public abstract boolean isEmpty();
     method public abstract java.util.Set<K> keySet();
+    method public default V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public abstract V put(K, V);
     method public abstract void putAll(java.util.Map<? extends K, ? extends V>);
+    method public default V putIfAbsent(K, V);
     method public abstract V remove(java.lang.Object);
+    method public default boolean remove(java.lang.Object, java.lang.Object);
+    method public default boolean replace(K, V, V);
+    method public default V replace(K, V);
+    method public default void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public abstract int size();
     method public abstract java.util.Collection<V> values();
   }
 
   public static abstract interface Map.Entry {
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey();
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>);
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue();
+    method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>);
     method public abstract boolean equals(java.lang.Object);
     method public abstract K getKey();
     method public abstract V getValue();
@@ -58257,6 +58560,7 @@
   public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
+    ctor public PriorityQueue(java.util.Comparator<? super E>);
     ctor public PriorityQueue(int, java.util.Comparator<? super E>);
     ctor public PriorityQueue(java.util.Collection<? extends E>);
     ctor public PriorityQueue(java.util.PriorityQueue<? extends E>);
@@ -58267,6 +58571,7 @@
     method public E peek();
     method public E poll();
     method public int size();
+    method public final java.util.Spliterator<E> spliterator();
   }
 
   public class Properties extends java.util.Hashtable {
@@ -58509,6 +58814,111 @@
     method public abstract java.util.SortedSet<E> tailSet(E);
   }
 
+  public abstract interface Spliterator {
+    method public abstract int characteristics();
+    method public abstract long estimateSize();
+    method public default void forEachRemaining(java.util.function.Consumer<? super T>);
+    method public default java.util.Comparator<? super T> getComparator();
+    method public default long getExactSizeIfKnown();
+    method public default boolean hasCharacteristics(int);
+    method public abstract boolean tryAdvance(java.util.function.Consumer<? super T>);
+    method public abstract java.util.Spliterator<T> trySplit();
+    field public static final int CONCURRENT = 4096; // 0x1000
+    field public static final int DISTINCT = 1; // 0x1
+    field public static final int IMMUTABLE = 1024; // 0x400
+    field public static final int NONNULL = 256; // 0x100
+    field public static final int ORDERED = 16; // 0x10
+    field public static final int SIZED = 64; // 0x40
+    field public static final int SORTED = 4; // 0x4
+    field public static final int SUBSIZED = 16384; // 0x4000
+  }
+
+  public static abstract interface Spliterator.OfDouble implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.DoubleConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+    method public abstract boolean tryAdvance(java.util.function.DoubleConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Double>);
+    method public abstract java.util.Spliterator.OfDouble trySplit();
+  }
+
+  public static abstract interface Spliterator.OfInt implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.IntConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+    method public abstract boolean tryAdvance(java.util.function.IntConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Integer>);
+    method public abstract java.util.Spliterator.OfInt trySplit();
+  }
+
+  public static abstract interface Spliterator.OfLong implements java.util.Spliterator.OfPrimitive {
+    method public default void forEachRemaining(java.util.function.LongConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+    method public abstract boolean tryAdvance(java.util.function.LongConsumer);
+    method public default boolean tryAdvance(java.util.function.Consumer<? super java.lang.Long>);
+    method public abstract java.util.Spliterator.OfLong trySplit();
+  }
+
+  public static abstract interface Spliterator.OfPrimitive implements java.util.Spliterator {
+    method public default void forEachRemaining(T_CONS);
+    method public abstract boolean tryAdvance(T_CONS);
+    method public abstract T_SPLITR trySplit();
+  }
+
+  public final class Spliterators {
+    method public static java.util.Spliterator.OfDouble emptyDoubleSpliterator();
+    method public static java.util.Spliterator.OfInt emptyIntSpliterator();
+    method public static java.util.Spliterator.OfLong emptyLongSpliterator();
+    method public static java.util.Spliterator<T> emptySpliterator();
+    method public static java.util.Iterator<T> iterator(java.util.Spliterator<? extends T>);
+    method public static java.util.PrimitiveIterator.OfInt iterator(java.util.Spliterator.OfInt);
+    method public static java.util.PrimitiveIterator.OfLong iterator(java.util.Spliterator.OfLong);
+    method public static java.util.PrimitiveIterator.OfDouble iterator(java.util.Spliterator.OfDouble);
+    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int);
+    method public static java.util.Spliterator<T> spliterator(java.lang.Object[], int, int, int);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int);
+    method public static java.util.Spliterator.OfInt spliterator(int[], int, int, int);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int);
+    method public static java.util.Spliterator.OfLong spliterator(long[], int, int, int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int);
+    method public static java.util.Spliterator.OfDouble spliterator(double[], int, int, int);
+    method public static java.util.Spliterator<T> spliterator(java.util.Collection<? extends T>, int);
+    method public static java.util.Spliterator<T> spliterator(java.util.Iterator<? extends T>, long, int);
+    method public static java.util.Spliterator.OfInt spliterator(java.util.PrimitiveIterator.OfInt, long, int);
+    method public static java.util.Spliterator.OfLong spliterator(java.util.PrimitiveIterator.OfLong, long, int);
+    method public static java.util.Spliterator.OfDouble spliterator(java.util.PrimitiveIterator.OfDouble, long, int);
+    method public static java.util.Spliterator<T> spliteratorUnknownSize(java.util.Iterator<? extends T>, int);
+    method public static java.util.Spliterator.OfInt spliteratorUnknownSize(java.util.PrimitiveIterator.OfInt, int);
+    method public static java.util.Spliterator.OfLong spliteratorUnknownSize(java.util.PrimitiveIterator.OfLong, int);
+    method public static java.util.Spliterator.OfDouble spliteratorUnknownSize(java.util.PrimitiveIterator.OfDouble, int);
+  }
+
+  public static abstract class Spliterators.AbstractDoubleSpliterator implements java.util.Spliterator.OfDouble {
+    ctor protected Spliterators.AbstractDoubleSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfDouble trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractIntSpliterator implements java.util.Spliterator.OfInt {
+    ctor protected Spliterators.AbstractIntSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfInt trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractLongSpliterator implements java.util.Spliterator.OfLong {
+    ctor protected Spliterators.AbstractLongSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator.OfLong trySplit();
+  }
+
+  public static abstract class Spliterators.AbstractSpliterator implements java.util.Spliterator {
+    ctor protected Spliterators.AbstractSpliterator(long, int);
+    method public int characteristics();
+    method public long estimateSize();
+    method public java.util.Spliterator<T> trySplit();
+  }
+
   public class Stack extends java.util.Vector {
     ctor public Stack();
     method public boolean empty();
@@ -58518,6 +58928,15 @@
     method public synchronized int search(java.lang.Object);
   }
 
+  public final class StringJoiner {
+    ctor public StringJoiner(java.lang.CharSequence);
+    ctor public StringJoiner(java.lang.CharSequence, java.lang.CharSequence, java.lang.CharSequence);
+    method public java.util.StringJoiner add(java.lang.CharSequence);
+    method public int length();
+    method public java.util.StringJoiner merge(java.util.StringJoiner);
+    method public java.util.StringJoiner setEmptyValue(java.lang.CharSequence);
+  }
+
   public class StringTokenizer implements java.util.Enumeration {
     ctor public StringTokenizer(java.lang.String, java.lang.String, boolean);
     ctor public StringTokenizer(java.lang.String, java.lang.String);
@@ -58639,6 +59058,7 @@
     method public E pollFirst();
     method public E pollLast();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
     method public java.util.SortedSet<E> subSet(E, E);
     method public java.util.NavigableSet<E> tailSet(E, boolean);
@@ -58692,9 +59112,11 @@
     method public synchronized void removeAllElements();
     method public synchronized boolean removeElement(java.lang.Object);
     method public synchronized void removeElementAt(int);
+    method public synchronized boolean removeIf(java.util.function.Predicate<? super E>);
     method public synchronized void setElementAt(E, int);
     method public synchronized void setSize(int);
     method public synchronized int size();
+    method public java.util.Spliterator<E> spliterator();
     method public synchronized void trimToSize();
     field protected int capacityIncrement;
     field protected int elementCount;
@@ -58742,6 +59164,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -58805,6 +59228,78 @@
     ctor public CancellationException(java.lang.String);
   }
 
+  public class CompletableFuture implements java.util.concurrent.CompletionStage java.util.concurrent.Future {
+    ctor public CompletableFuture();
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> allOf(java.util.concurrent.CompletableFuture<?>...);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Object> anyOf(java.util.concurrent.CompletableFuture<?>...);
+    method public java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public boolean cancel(boolean);
+    method public boolean complete(T);
+    method public boolean completeExceptionally(java.lang.Throwable);
+    method public static java.util.concurrent.CompletableFuture<U> completedFuture(U);
+    method public java.util.concurrent.CompletableFuture<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
+    method public T get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public T get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public T getNow(T);
+    method public int getNumberOfDependents();
+    method public java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public boolean isCancelled();
+    method public boolean isCompletedExceptionally();
+    method public boolean isDone();
+    method public T join();
+    method public void obtrudeException(java.lang.Throwable);
+    method public void obtrudeValue(T);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable);
+    method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>);
+    method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRun(java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public java.util.concurrent.CompletableFuture<T> toCompletableFuture();
+    method public java.util.concurrent.CompletableFuture<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
+  }
+
+  public static abstract interface CompletableFuture.AsynchronousCompletionTask {
+  }
+
+  public class CompletionException extends java.lang.RuntimeException {
+    ctor protected CompletionException();
+    ctor protected CompletionException(java.lang.String);
+    ctor public CompletionException(java.lang.String, java.lang.Throwable);
+    ctor public CompletionException(java.lang.Throwable);
+  }
+
   public abstract interface CompletionService {
     method public abstract java.util.concurrent.Future<V> poll();
     method public abstract java.util.concurrent.Future<V> poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
@@ -58813,20 +59308,130 @@
     method public abstract java.util.concurrent.Future<V> take() throws java.lang.InterruptedException;
   }
 
+  public abstract interface CompletionStage {
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>);
+    method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>);
+    method public abstract java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>);
+    method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>);
+    method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRun(java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable);
+    method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor);
+    method public abstract java.util.concurrent.CompletableFuture<T> toCompletableFuture();
+    method public abstract java.util.concurrent.CompletionStage<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>);
+    method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor);
+  }
+
   public class ConcurrentHashMap extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable {
     ctor public ConcurrentHashMap();
     ctor public ConcurrentHashMap(int);
     ctor public ConcurrentHashMap(java.util.Map<? extends K, ? extends V>);
     ctor public ConcurrentHashMap(int, float);
     ctor public ConcurrentHashMap(int, float, int);
+    method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public boolean contains(java.lang.Object);
     method public java.util.Enumeration<V> elements();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public void forEach(long, java.util.function.BiConsumer<? super K, ? super V>);
+    method public void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachEntry(long, java.util.function.Consumer<? super java.util.Map.Entry<K, V>>);
+    method public void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachKey(long, java.util.function.Consumer<? super K>);
+    method public void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>);
+    method public void forEachValue(long, java.util.function.Consumer<? super V>);
+    method public void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>);
+    method public V getOrDefault(java.lang.Object, V);
+    method public java.util.concurrent.ConcurrentHashMap.KeySetView<K, V> keySet(V);
     method public java.util.Enumeration<K> keys();
+    method public long mappingCount();
+    method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
+    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet();
+    method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int);
     method public V putIfAbsent(K, V);
+    method public U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public java.util.Map.Entry<K, V> reduceEntries(long, java.util.function.BiFunction<java.util.Map.Entry<K, V>, java.util.Map.Entry<K, V>, ? extends java.util.Map.Entry<K, V>>);
+    method public U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceEntriesToDouble(long, java.util.function.ToDoubleFunction<java.util.Map.Entry<K, V>>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceEntriesToInt(long, java.util.function.ToIntFunction<java.util.Map.Entry<K, V>>, int, java.util.function.IntBinaryOperator);
+    method public long reduceEntriesToLong(long, java.util.function.ToLongFunction<java.util.Map.Entry<K, V>>, long, java.util.function.LongBinaryOperator);
+    method public K reduceKeys(long, java.util.function.BiFunction<? super K, ? super K, ? extends K>);
+    method public U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceKeysToDouble(long, java.util.function.ToDoubleFunction<? super K>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceKeysToInt(long, java.util.function.ToIntFunction<? super K>, int, java.util.function.IntBinaryOperator);
+    method public long reduceKeysToLong(long, java.util.function.ToLongFunction<? super K>, long, java.util.function.LongBinaryOperator);
+    method public double reduceToDouble(long, java.util.function.ToDoubleBiFunction<? super K, ? super V>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceToInt(long, java.util.function.ToIntBiFunction<? super K, ? super V>, int, java.util.function.IntBinaryOperator);
+    method public long reduceToLong(long, java.util.function.ToLongBiFunction<? super K, ? super V>, long, java.util.function.LongBinaryOperator);
+    method public V reduceValues(long, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
+    method public U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>);
+    method public double reduceValuesToDouble(long, java.util.function.ToDoubleFunction<? super V>, double, java.util.function.DoubleBinaryOperator);
+    method public int reduceValuesToInt(long, java.util.function.ToIntFunction<? super V>, int, java.util.function.IntBinaryOperator);
+    method public long reduceValuesToLong(long, java.util.function.ToLongFunction<? super V>, long, java.util.function.LongBinaryOperator);
     method public boolean remove(java.lang.Object, java.lang.Object);
     method public boolean replace(K, V, V);
     method public V replace(K, V);
+    method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>);
+    method public U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>);
+    method public U searchKeys(long, java.util.function.Function<? super K, ? extends U>);
+    method public U searchValues(long, java.util.function.Function<? super V, ? extends U>);
+  }
+
+   static abstract class ConcurrentHashMap.CollectionView implements java.util.Collection java.io.Serializable {
+    method public final void clear();
+    method public abstract boolean contains(java.lang.Object);
+    method public final boolean containsAll(java.util.Collection<?>);
+    method public java.util.concurrent.ConcurrentHashMap<K, V> getMap();
+    method public final boolean isEmpty();
+    method public abstract java.util.Iterator<E> iterator();
+    method public abstract boolean remove(java.lang.Object);
+    method public final boolean removeAll(java.util.Collection<?>);
+    method public final boolean retainAll(java.util.Collection<?>);
+    method public final int size();
+    method public final java.lang.Object[] toArray();
+    method public final T[] toArray(T[]);
+    method public final java.lang.String toString();
+  }
+
+  public static class ConcurrentHashMap.KeySetView extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set {
+    method public boolean add(K);
+    method public boolean addAll(java.util.Collection<? extends K>);
+    method public boolean contains(java.lang.Object);
+    method public void forEach(java.util.function.Consumer<? super K>);
+    method public V getMappedValue();
+    method public java.util.Iterator<K> iterator();
+    method public boolean remove(java.lang.Object);
+    method public java.util.Spliterator<K> spliterator();
   }
 
   public class ConcurrentLinkedDeque extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable {
@@ -58856,6 +59461,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable {
@@ -58866,6 +59472,7 @@
     method public E peek();
     method public E poll();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public abstract interface ConcurrentMap implements java.util.Map {
@@ -58897,6 +59504,9 @@
     method public K ceilingKey(K);
     method public java.util.concurrent.ConcurrentSkipListMap<K, V> clone();
     method public java.util.Comparator<? super K> comparator();
+    method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public java.util.NavigableSet<K> descendingKeySet();
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> descendingMap();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
@@ -58904,6 +59514,8 @@
     method public K firstKey();
     method public java.util.Map.Entry<K, V> floorEntry(K);
     method public K floorKey(K);
+    method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public V getOrDefault(java.lang.Object, V);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K, boolean);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K);
     method public java.util.Map.Entry<K, V> higherEntry(K);
@@ -58912,6 +59524,7 @@
     method public K lastKey();
     method public java.util.Map.Entry<K, V> lowerEntry(K);
     method public K lowerKey(K);
+    method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public java.util.NavigableSet<K> navigableKeySet();
     method public java.util.Map.Entry<K, V> pollFirstEntry();
     method public java.util.Map.Entry<K, V> pollLastEntry();
@@ -58919,6 +59532,7 @@
     method public boolean remove(java.lang.Object, java.lang.Object);
     method public boolean replace(K, V, V);
     method public V replace(K, V);
+    method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, boolean, K, boolean);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, K);
     method public java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K, boolean);
@@ -58946,6 +59560,7 @@
     method public E pollFirst();
     method public E pollLast();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean);
     method public java.util.NavigableSet<E> subSet(E, E);
     method public java.util.NavigableSet<E> tailSet(E, boolean);
@@ -58989,8 +59604,11 @@
   public class CopyOnWriteArraySet extends java.util.AbstractSet implements java.io.Serializable {
     ctor public CopyOnWriteArraySet();
     ctor public CopyOnWriteArraySet(java.util.Collection<? extends E>);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public java.util.Iterator<E> iterator();
+    method public boolean removeIf(java.util.function.Predicate<? super E>);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
   }
 
   public class CountDownLatch {
@@ -59001,6 +59619,32 @@
     method public long getCount();
   }
 
+  public abstract class CountedCompleter extends java.util.concurrent.ForkJoinTask {
+    ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>, int);
+    ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>);
+    ctor protected CountedCompleter();
+    method public final void addToPendingCount(int);
+    method public final boolean compareAndSetPendingCount(int, int);
+    method public void complete(T);
+    method public abstract void compute();
+    method public final int decrementPendingCountUnlessZero();
+    method protected final boolean exec();
+    method public final java.util.concurrent.CountedCompleter<?> firstComplete();
+    method public final java.util.concurrent.CountedCompleter<?> getCompleter();
+    method public final int getPendingCount();
+    method public T getRawResult();
+    method public final java.util.concurrent.CountedCompleter<?> getRoot();
+    method public final void helpComplete(int);
+    method public final java.util.concurrent.CountedCompleter<?> nextComplete();
+    method public void onCompletion(java.util.concurrent.CountedCompleter<?>);
+    method public boolean onExceptionalCompletion(java.lang.Throwable, java.util.concurrent.CountedCompleter<?>);
+    method public final void propagateCompletion();
+    method public final void quietlyCompleteRoot();
+    method public final void setPendingCount(int);
+    method protected void setRawResult(T);
+    method public final void tryComplete();
+  }
+
   public class CyclicBarrier {
     ctor public CyclicBarrier(int, java.lang.Runnable);
     ctor public CyclicBarrier(int);
@@ -59091,6 +59735,8 @@
     method public static java.util.concurrent.ExecutorService newSingleThreadExecutor(java.util.concurrent.ThreadFactory);
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor();
     method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory);
+    method public static java.util.concurrent.ExecutorService newWorkStealingPool(int);
+    method public static java.util.concurrent.ExecutorService newWorkStealingPool();
     method public static java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>);
     method public static java.util.concurrent.ThreadFactory privilegedThreadFactory();
@@ -59104,11 +59750,13 @@
     ctor public ForkJoinPool(int, java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory, java.lang.Thread.UncaughtExceptionHandler, boolean);
     method public boolean awaitQuiescence(long, java.util.concurrent.TimeUnit);
     method public boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public static java.util.concurrent.ForkJoinPool commonPool();
     method protected int drainTasksTo(java.util.Collection<? super java.util.concurrent.ForkJoinTask<?>>);
     method public void execute(java.util.concurrent.ForkJoinTask<?>);
     method public void execute(java.lang.Runnable);
     method public int getActiveThreadCount();
     method public boolean getAsyncMode();
+    method public static int getCommonPoolParallelism();
     method public java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory getFactory();
     method public int getParallelism();
     method public int getPoolSize();
@@ -59146,6 +59794,7 @@
     method public static java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T);
     method public static java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>);
     method public boolean cancel(boolean);
+    method public final boolean compareAndSetForkJoinTaskTag(short, short);
     method public void complete(V);
     method public void completeExceptionally(java.lang.Throwable);
     method protected abstract boolean exec();
@@ -59153,6 +59802,7 @@
     method public final V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
     method public final V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
     method public final java.lang.Throwable getException();
+    method public final short getForkJoinTaskTag();
     method public static java.util.concurrent.ForkJoinPool getPool();
     method public static int getQueuedTaskCount();
     method public abstract V getRawResult();
@@ -59171,9 +59821,11 @@
     method protected static java.util.concurrent.ForkJoinTask<?> peekNextLocalTask();
     method protected static java.util.concurrent.ForkJoinTask<?> pollNextLocalTask();
     method protected static java.util.concurrent.ForkJoinTask<?> pollTask();
+    method public final void quietlyComplete();
     method public final void quietlyInvoke();
     method public final void quietlyJoin();
     method public void reinitialize();
+    method public final short setForkJoinTaskTag(short);
     method protected abstract void setRawResult(V);
     method public boolean tryUnfork();
   }
@@ -59247,6 +59899,7 @@
     method public E removeLast();
     method public boolean removeLastOccurrence(java.lang.Object);
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
     method public E takeFirst() throws java.lang.InterruptedException;
     method public E takeLast() throws java.lang.InterruptedException;
@@ -59267,6 +59920,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -59286,6 +59940,7 @@
     method public void put(E);
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
     method public void transfer(E) throws java.lang.InterruptedException;
     method public boolean tryTransfer(E);
@@ -59333,6 +59988,7 @@
     method public void put(E);
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -59436,6 +60092,7 @@
     method public void put(E) throws java.lang.InterruptedException;
     method public int remainingCapacity();
     method public int size();
+    method public java.util.Spliterator<E> spliterator();
     method public E take() throws java.lang.InterruptedException;
   }
 
@@ -59565,112 +60222,136 @@
   public class AtomicInteger extends java.lang.Number implements java.io.Serializable {
     ctor public AtomicInteger(int);
     ctor public AtomicInteger();
+    method public final int accumulateAndGet(int, java.util.function.IntBinaryOperator);
     method public final int addAndGet(int);
     method public final boolean compareAndSet(int, int);
     method public final int decrementAndGet();
     method public double doubleValue();
     method public float floatValue();
     method public final int get();
+    method public final int getAndAccumulate(int, java.util.function.IntBinaryOperator);
     method public final int getAndAdd(int);
     method public final int getAndDecrement();
     method public final int getAndIncrement();
     method public final int getAndSet(int);
+    method public final int getAndUpdate(java.util.function.IntUnaryOperator);
     method public final int incrementAndGet();
     method public int intValue();
     method public final void lazySet(int);
     method public long longValue();
     method public final void set(int);
+    method public final int updateAndGet(java.util.function.IntUnaryOperator);
     method public final boolean weakCompareAndSet(int, int);
   }
 
   public class AtomicIntegerArray implements java.io.Serializable {
     ctor public AtomicIntegerArray(int);
     ctor public AtomicIntegerArray(int[]);
+    method public final int accumulateAndGet(int, int, java.util.function.IntBinaryOperator);
     method public final int addAndGet(int, int);
     method public final boolean compareAndSet(int, int, int);
     method public final int decrementAndGet(int);
     method public final int get(int);
+    method public final int getAndAccumulate(int, int, java.util.function.IntBinaryOperator);
     method public final int getAndAdd(int, int);
     method public final int getAndDecrement(int);
     method public final int getAndIncrement(int);
     method public final int getAndSet(int, int);
+    method public final int getAndUpdate(int, java.util.function.IntUnaryOperator);
     method public final int incrementAndGet(int);
     method public final void lazySet(int, int);
     method public final int length();
     method public final void set(int, int);
+    method public final int updateAndGet(int, java.util.function.IntUnaryOperator);
     method public final boolean weakCompareAndSet(int, int, int);
   }
 
   public abstract class AtomicIntegerFieldUpdater {
     ctor protected AtomicIntegerFieldUpdater();
+    method public final int accumulateAndGet(T, int, java.util.function.IntBinaryOperator);
     method public int addAndGet(T, int);
     method public abstract boolean compareAndSet(T, int, int);
     method public int decrementAndGet(T);
     method public abstract int get(T);
+    method public final int getAndAccumulate(T, int, java.util.function.IntBinaryOperator);
     method public int getAndAdd(T, int);
     method public int getAndDecrement(T);
     method public int getAndIncrement(T);
     method public int getAndSet(T, int);
+    method public final int getAndUpdate(T, java.util.function.IntUnaryOperator);
     method public int incrementAndGet(T);
     method public abstract void lazySet(T, int);
     method public static java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, int);
+    method public final int updateAndGet(T, java.util.function.IntUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, int, int);
   }
 
   public class AtomicLong extends java.lang.Number implements java.io.Serializable {
     ctor public AtomicLong(long);
     ctor public AtomicLong();
+    method public final long accumulateAndGet(long, java.util.function.LongBinaryOperator);
     method public final long addAndGet(long);
     method public final boolean compareAndSet(long, long);
     method public final long decrementAndGet();
     method public double doubleValue();
     method public float floatValue();
     method public final long get();
+    method public final long getAndAccumulate(long, java.util.function.LongBinaryOperator);
     method public final long getAndAdd(long);
     method public final long getAndDecrement();
     method public final long getAndIncrement();
     method public final long getAndSet(long);
+    method public final long getAndUpdate(java.util.function.LongUnaryOperator);
     method public final long incrementAndGet();
     method public int intValue();
     method public final void lazySet(long);
     method public long longValue();
     method public final void set(long);
+    method public final long updateAndGet(java.util.function.LongUnaryOperator);
     method public final boolean weakCompareAndSet(long, long);
   }
 
   public class AtomicLongArray implements java.io.Serializable {
     ctor public AtomicLongArray(int);
     ctor public AtomicLongArray(long[]);
+    method public final long accumulateAndGet(int, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(int, long);
     method public final boolean compareAndSet(int, long, long);
     method public final long decrementAndGet(int);
     method public final long get(int);
+    method public final long getAndAccumulate(int, long, java.util.function.LongBinaryOperator);
     method public final long getAndAdd(int, long);
     method public final long getAndDecrement(int);
     method public final long getAndIncrement(int);
     method public final long getAndSet(int, long);
+    method public final long getAndUpdate(int, java.util.function.LongUnaryOperator);
     method public final long incrementAndGet(int);
     method public final void lazySet(int, long);
     method public final int length();
     method public final void set(int, long);
+    method public final long updateAndGet(int, java.util.function.LongUnaryOperator);
     method public final boolean weakCompareAndSet(int, long, long);
   }
 
   public abstract class AtomicLongFieldUpdater {
     ctor protected AtomicLongFieldUpdater();
+    method public final long accumulateAndGet(T, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(T, long);
     method public abstract boolean compareAndSet(T, long, long);
     method public long decrementAndGet(T);
     method public abstract long get(T);
+    method public final long getAndAccumulate(T, long, java.util.function.LongBinaryOperator);
     method public long getAndAdd(T, long);
     method public long getAndDecrement(T);
     method public long getAndIncrement(T);
     method public long getAndSet(T, long);
+    method public final long getAndUpdate(T, java.util.function.LongUnaryOperator);
     method public long incrementAndGet(T);
     method public abstract void lazySet(T, long);
     method public static java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String);
     method public abstract void set(T, long);
+    method public final long updateAndGet(T, java.util.function.LongUnaryOperator);
     method public abstract boolean weakCompareAndSet(T, long, long);
   }
 
@@ -59688,34 +60369,46 @@
   public class AtomicReference implements java.io.Serializable {
     ctor public AtomicReference(V);
     ctor public AtomicReference();
+    method public final V accumulateAndGet(V, java.util.function.BinaryOperator<V>);
     method public final boolean compareAndSet(V, V);
     method public final V get();
+    method public final V getAndAccumulate(V, java.util.function.BinaryOperator<V>);
     method public final V getAndSet(V);
+    method public final V getAndUpdate(java.util.function.UnaryOperator<V>);
     method public final void lazySet(V);
     method public final void set(V);
+    method public final V updateAndGet(java.util.function.UnaryOperator<V>);
     method public final boolean weakCompareAndSet(V, V);
   }
 
   public class AtomicReferenceArray implements java.io.Serializable {
     ctor public AtomicReferenceArray(int);
     ctor public AtomicReferenceArray(E[]);
+    method public final E accumulateAndGet(int, E, java.util.function.BinaryOperator<E>);
     method public final boolean compareAndSet(int, E, E);
     method public final E get(int);
+    method public final E getAndAccumulate(int, E, java.util.function.BinaryOperator<E>);
     method public final E getAndSet(int, E);
+    method public final E getAndUpdate(int, java.util.function.UnaryOperator<E>);
     method public final void lazySet(int, E);
     method public final int length();
     method public final void set(int, E);
+    method public final E updateAndGet(int, java.util.function.UnaryOperator<E>);
     method public final boolean weakCompareAndSet(int, E, E);
   }
 
   public abstract class AtomicReferenceFieldUpdater {
     ctor protected AtomicReferenceFieldUpdater();
+    method public final V accumulateAndGet(T, V, java.util.function.BinaryOperator<V>);
     method public abstract boolean compareAndSet(T, V, V);
     method public abstract V get(T);
+    method public final V getAndAccumulate(T, V, java.util.function.BinaryOperator<V>);
     method public V getAndSet(T, V);
+    method public final V getAndUpdate(T, java.util.function.UnaryOperator<V>);
     method public abstract void lazySet(T, V);
     method public static java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String);
     method public abstract void set(T, V);
+    method public final V updateAndGet(T, java.util.function.UnaryOperator<V>);
     method public abstract boolean weakCompareAndSet(T, V, V);
   }
 
@@ -59730,6 +60423,59 @@
     method public boolean weakCompareAndSet(V, V, int, int);
   }
 
+  public class DoubleAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public DoubleAccumulator(java.util.function.DoubleBinaryOperator, double);
+    method public void accumulate(double);
+    method public double doubleValue();
+    method public float floatValue();
+    method public double get();
+    method public double getThenReset();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+  }
+
+  public class DoubleAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public DoubleAdder();
+    method public void add(double);
+    method public double doubleValue();
+    method public float floatValue();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+    method public double sum();
+    method public double sumThenReset();
+  }
+
+  public class LongAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public LongAccumulator(java.util.function.LongBinaryOperator, long);
+    method public void accumulate(long);
+    method public double doubleValue();
+    method public float floatValue();
+    method public long get();
+    method public long getThenReset();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+  }
+
+  public class LongAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable {
+    ctor public LongAdder();
+    method public void add(long);
+    method public void decrement();
+    method public double doubleValue();
+    method public float floatValue();
+    method public void increment();
+    method public int intValue();
+    method public long longValue();
+    method public void reset();
+    method public long sum();
+    method public long sumThenReset();
+  }
+
+   abstract class Striped64 extends java.lang.Number {
+  }
+
 }
 
 package java.util.concurrent.locks {
@@ -59937,6 +60683,34 @@
     method public void unlock();
   }
 
+  public class StampedLock implements java.io.Serializable {
+    ctor public StampedLock();
+    method public java.util.concurrent.locks.Lock asReadLock();
+    method public java.util.concurrent.locks.ReadWriteLock asReadWriteLock();
+    method public java.util.concurrent.locks.Lock asWriteLock();
+    method public int getReadLockCount();
+    method public boolean isReadLocked();
+    method public boolean isWriteLocked();
+    method public long readLock();
+    method public long readLockInterruptibly() throws java.lang.InterruptedException;
+    method public long tryConvertToOptimisticRead(long);
+    method public long tryConvertToReadLock(long);
+    method public long tryConvertToWriteLock(long);
+    method public long tryOptimisticRead();
+    method public long tryReadLock();
+    method public long tryReadLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public boolean tryUnlockRead();
+    method public boolean tryUnlockWrite();
+    method public long tryWriteLock();
+    method public long tryWriteLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public void unlock(long);
+    method public void unlockRead(long);
+    method public void unlockWrite(long);
+    method public boolean validate(long);
+    method public long writeLock();
+    method public long writeLockInterruptibly() throws java.lang.InterruptedException;
+  }
+
 }
 
 package java.util.function {
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 2f55373..8ac2d63 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -35,6 +35,25 @@
 
 }
 
+package android.graphics {
+
+  public deprecated class AvoidXfermode extends android.graphics.Xfermode {
+    ctor public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode);
+  }
+
+  public static final class AvoidXfermode.Mode extends java.lang.Enum {
+    method public static android.graphics.AvoidXfermode.Mode valueOf(java.lang.String);
+    method public static final android.graphics.AvoidXfermode.Mode[] values();
+    enum_constant public static final android.graphics.AvoidXfermode.Mode AVOID;
+    enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET;
+  }
+
+  public deprecated class PixelXorXfermode extends android.graphics.Xfermode {
+    ctor public PixelXorXfermode(int);
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index c469ae4..7bf073b 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -67,30 +67,6 @@
     }
 }
 
-static status_t vinfoToPixelFormat(const fb_var_screeninfo& vinfo,
-        uint32_t* bytespp, uint32_t* f)
-{
-
-    switch (vinfo.bits_per_pixel) {
-        case 16:
-            *f = PIXEL_FORMAT_RGB_565;
-            *bytespp = 2;
-            break;
-        case 24:
-            *f = PIXEL_FORMAT_RGB_888;
-            *bytespp = 3;
-            break;
-        case 32:
-            // TODO: do better decoding of vinfo here
-            *f = PIXEL_FORMAT_RGBX_8888;
-            *bytespp = 4;
-            break;
-        default:
-            return BAD_VALUE;
-    }
-    return NO_ERROR;
-}
-
 static status_t notifyMediaScanner(const char* fileName) {
     String8 cmd("am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://");
     String8 fileUrl("\"");
@@ -147,7 +123,7 @@
             png = true;
         }
     }
-    
+
     if (fd == -1) {
         usage(pname);
         return 1;
@@ -195,28 +171,6 @@
         s = screenshot.getStride();
         f = screenshot.getFormat();
         size = screenshot.getSize();
-    } else {
-        const char* fbpath = "/dev/graphics/fb0";
-        int fb = open(fbpath, O_RDONLY);
-        if (fb >= 0) {
-            struct fb_var_screeninfo vinfo;
-            if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) == 0) {
-                uint32_t bytespp;
-                if (vinfoToPixelFormat(vinfo, &bytespp, &f) == NO_ERROR) {
-                    size_t offset = (vinfo.xoffset + vinfo.yoffset*vinfo.xres) * bytespp;
-                    w = vinfo.xres;
-                    h = vinfo.yres;
-                    s = vinfo.xres;
-                    size = w*h*bytespp;
-                    mapsize = offset + size;
-                    mapbase = mmap(0, mapsize, PROT_READ, MAP_PRIVATE, fb, 0);
-                    if (mapbase != MAP_FAILED) {
-                        base = (void const *)((char const *)mapbase + offset);
-                    }
-                }
-            }
-            close(fb);
-        }
     }
 
     if (base != NULL) {
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 844063c..8e31d32 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -16,6 +16,7 @@
 
 package android.animation;
 
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.ConstantState;
 
 import java.util.ArrayList;
@@ -50,7 +51,7 @@
      * A set of flags which identify the type of configuration changes that can affect this
      * Animator. Used by the Animator cache.
      */
-    int mChangingConfigurations = 0;
+    @Config int mChangingConfigurations = 0;
 
     /**
      * If this animator is inflated from a constant state, keep a reference to it so that
@@ -344,7 +345,7 @@
      * @see android.content.pm.ActivityInfo
      * @hide
      */
-    public int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         return mChangingConfigurations;
     }
 
@@ -358,7 +359,7 @@
      * @see android.content.pm.ActivityInfo
      * @hide
      */
-    public void setChangingConfigurations(int configs) {
+    public void setChangingConfigurations(@Config int configs) {
         mChangingConfigurations = configs;
     }
 
@@ -368,7 +369,7 @@
      * This method is called while loading the animator.
      * @hide
      */
-    public void appendChangingConfigurations(int configs) {
+    public void appendChangingConfigurations(@Config int configs) {
         mChangingConfigurations |= configs;
     }
 
@@ -564,7 +565,7 @@
     private static class AnimatorConstantState extends ConstantState<Animator> {
 
         final Animator mAnimator;
-        int mChangingConf;
+        @Config int mChangingConf;
 
         public AnimatorConstantState(Animator animator) {
             mAnimator = animator;
@@ -574,7 +575,7 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mChangingConf;
         }
 
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 8d03b55..7d5931f 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -16,7 +16,10 @@
 package android.animation;
 
 import android.annotation.AnimatorRes;
+import android.annotation.AnyRes;
+import android.annotation.NonNull;
 import android.content.Context;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.ConfigurationBoundResourceCache;
 import android.content.res.ConstantState;
 import android.content.res.Resources;
@@ -1062,7 +1065,7 @@
         return anim;
     }
 
-    private static int getChangingConfigs(Resources resources, int id) {
+    private static @Config int getChangingConfigs(@NonNull Resources resources, @AnyRes int id) {
         synchronized (sTmpTypedValue) {
             resources.getValue(id, sTmpTypedValue, true);
             return sTmpTypedValue.changingConfigurations;
diff --git a/core/java/android/animation/StateListAnimator.java b/core/java/android/animation/StateListAnimator.java
index d49e914..b6d6910 100644
--- a/core/java/android/animation/StateListAnimator.java
+++ b/core/java/android/animation/StateListAnimator.java
@@ -16,6 +16,7 @@
 
 package android.animation;
 
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.ConstantState;
 import android.util.StateSet;
 import android.view.View;
@@ -53,7 +54,7 @@
     private WeakReference<View> mViewRef;
     private StateListAnimatorConstantState mConstantState;
     private AnimatorListenerAdapter mAnimatorListener;
-    private int mChangingConfigurations;
+    private @Config int mChangingConfigurations;
 
     public StateListAnimator() {
         initAnimatorListener();
@@ -223,7 +224,7 @@
      * @see android.content.pm.ActivityInfo
      * @hide
      */
-    public int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         return mChangingConfigurations;
     }
 
@@ -237,7 +238,7 @@
      * @see android.content.pm.ActivityInfo
      * @hide
      */
-    public void setChangingConfigurations(int configs) {
+    public void setChangingConfigurations(@Config int configs) {
         mChangingConfigurations = configs;
     }
 
@@ -247,7 +248,7 @@
      * This method is called while loading the animator.
      * @hide
      */
-    public void appendChangingConfigurations(int configs) {
+    public void appendChangingConfigurations(@Config int configs) {
         mChangingConfigurations |= configs;
     }
 
@@ -309,7 +310,7 @@
 
         final StateListAnimator mAnimator;
 
-        int mChangingConf;
+        @Config int mChangingConf;
 
         public StateListAnimatorConstantState(StateListAnimator animator) {
             mAnimator = animator;
@@ -318,7 +319,7 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mChangingConf;
         }
 
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 5ab2c1d..663f297 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -972,7 +972,14 @@
             // to be consistent with the previous behavior. Otherwise, postpone this until the first
             // frame after the start delay.
             startAnimation();
-            setCurrentFraction(mSeekFraction == -1 ? 0 : mSeekFraction);
+            if (mSeekFraction == -1) {
+                // No seek, start at play time 0. Note that the reason we are not using fraction 0
+                // is because for animations with 0 duration, we want to be consistent with pre-N
+                // behavior: skip to the final value immediately.
+                setCurrentPlayTime(0);
+            } else {
+                setCurrentFraction(mSeekFraction);
+            }
         }
     }
 
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 6b67b95..a0a599e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1976,15 +1976,13 @@
      * normal {@link #onSaveInstanceState(Bundle)} mechanism) even if this
      * function returns null.
      *
-     * @return Returns the object previously returned by
-     * {@link #onRetainNonConfigurationInstance()}.
-     *
-     * @deprecated Use the new {@link Fragment} API
+     * <p><strong>Note:</strong> For most cases you should use the {@link Fragment} API
      * {@link Fragment#setRetainInstance(boolean)} instead; this is also
-     * available on older platforms through the Android compatibility package.
+     * available on older platforms through the Android support libraries.
+     *
+     * @return the object previously returned by {@link #onRetainNonConfigurationInstance()}
      */
     @Nullable
-    @Deprecated
     public Object getLastNonConfigurationInstance() {
         return mLastNonConfigurationInstances != null
                 ? mLastNonConfigurationInstances.activity : null;
@@ -2035,12 +2033,12 @@
      * guarantee for {@link android.os.AsyncTask#doInBackground} since that is
      * running in a separate thread.)
      *
-     * @return Return any Object holding the desired state to propagate to the
-     * next activity instance.
-     *
-     * @deprecated Use the new {@link Fragment} API
+     * <p><strong>Note:</strong> For most cases you should use the {@link Fragment} API
      * {@link Fragment#setRetainInstance(boolean)} instead; this is also
-     * available on older platforms through the Android compatibility package.
+     * available on older platforms through the Android support libraries.
+     *
+     * @return any Object holding the desired state to propagate to the
+     *         next activity instance
      */
     public Object onRetainNonConfigurationInstance() {
         return null;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 2f6907e..2d33a2c 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3329,6 +3329,23 @@
         }
     }
 
+    /**
+     * Logs out current current foreground user by switching to the system user and stopping the
+     * user being switched from.
+     * @hide
+     */
+    public static void logoutCurrentUser() {
+        int currentUser = ActivityManager.getCurrentUser();
+        if (currentUser != UserHandle.USER_SYSTEM) {
+            try {
+                ActivityManagerNative.getDefault().switchUser(UserHandle.USER_SYSTEM);
+                ActivityManagerNative.getDefault().stopUser(currentUser, /* force= */ false, null);
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+        }
+    }
+
     /** {@hide} */
     public static final int FLAG_OR_STOPPED = 1 << 0;
     /** {@hide} */
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 6fbb430..811a05b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -838,6 +838,12 @@
             resizePinnedStack(bounds, tempPinnedTaskBounds);
             return true;
         }
+        case SWAP_DOCKED_AND_FULLSCREEN_STACK: {
+            data.enforceInterface(IActivityManager.descriptor);
+            swapDockedAndFullscreenStack();
+            reply.writeNoException();
+            return true;
+        }
         case RESIZE_DOCKED_STACK_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             final boolean hasBounds = data.readInt() != 0;
@@ -2301,7 +2307,7 @@
 
         case KEYGUARD_GOING_AWAY_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
-            keyguardGoingAway(data.readInt() != 0, data.readInt() != 0);
+            keyguardGoingAway(data.readInt());
             reply.writeNoException();
             return true;
         }
@@ -3895,6 +3901,17 @@
         reply.recycle();
     }
     @Override
+    public void swapDockedAndFullscreenStack() throws RemoteException
+    {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        mRemote.transact(SWAP_DOCKED_AND_FULLSCREEN_STACK, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+    @Override
     public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds,
             Rect tempDockedTaskInsetBounds,
             Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds)
@@ -5907,13 +5924,12 @@
         reply.recycle();
     }
 
-    public void keyguardGoingAway(boolean disableWindowAnimations,
-            boolean keyguardGoingToNotificationShade) throws RemoteException {
+    public void keyguardGoingAway(int flags)
+            throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
-        data.writeInt(disableWindowAnimations ? 1 : 0);
-        data.writeInt(keyguardGoingToNotificationShade ? 1 : 0);
+        data.writeInt(flags);
         mRemote.transact(KEYGUARD_GOING_AWAY_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 094950b..a6e7d67 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -710,6 +710,10 @@
 
     /** @hide */
     public ActivityOptions(Bundle opts) {
+        // If the remote side sent us bad parcelables, they won't get the
+        // results they want, which is their loss.
+        opts.setDefusable(true);
+
         mPackageName = opts.getString(KEY_PACKAGE_NAME);
         try {
             mUsageTimeReport = opts.getParcelable(KEY_USAGE_TIME_REPORT);
@@ -777,15 +781,16 @@
 
     /**
      * Sets the bounds (window size) that the activity should be launched in.
+     * Rect position should be provided in pixels and in screen coordinates.
      * Set to null explicitly for fullscreen.
      * <p>
      * <strong>NOTE:<strong/> This value is ignored on devices that don't have
      * {@link android.content.pm.PackageManager#FEATURE_FREEFORM_WINDOW_MANAGEMENT} or
      * {@link android.content.pm.PackageManager#FEATURE_PICTURE_IN_PICTURE} enabled.
-     * @param launchBounds Launch bounds to use for the activity or null for fullscreen.
+     * @param screenSpacePixelRect Launch bounds to use for the activity or null for fullscreen.
      */
-    public ActivityOptions setLaunchBounds(@Nullable Rect launchBounds) {
-        mLaunchBounds = launchBounds != null ? new Rect(launchBounds) : null;
+    public ActivityOptions setLaunchBounds(@Nullable Rect screenSpacePixelRect) {
+        mLaunchBounds = screenSpacePixelRect != null ? new Rect(screenSpacePixelRect) : null;
         return this;
     }
 
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index a452d20..060ac5e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1793,24 +1793,9 @@
      * Resources if one has already been created.
      */
     Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
-            String[] libDirs, int displayId, Configuration overrideConfiguration,
-            LoadedApk pkgInfo) {
-        return mResourcesManager.getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs,
-                displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo(),
-                pkgInfo.getClassLoader());
-    }
-
-    /**
-     * Creates a new top level resources for the given package. Will always create a new
-     * Resources, regardless if one has already been created.
-     */
-    Resources getNewTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
-            String[] libDirs, int displayId, Configuration overrideConfiguration,
-            LoadedApk pkgInfo) {
-        mResourcesManager.removeTopLevelResources(
-                resDir, displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo());
-        return getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs,
-                displayId, overrideConfiguration, pkgInfo);
+            String[] libDirs, int displayId, LoadedApk pkgInfo) {
+        return mResourcesManager.getResources(null, resDir, splitResDirs, overlayDirs, libDirs,
+                displayId, null, pkgInfo.getCompatibilityInfo(), pkgInfo.getClassLoader());
     }
 
     final Handler getHandler() {
@@ -2624,7 +2609,7 @@
         }
 
         ContextImpl appContext = ContextImpl.createActivityContext(
-                this, r.packageInfo, displayId, r.overrideConfig);
+                this, r.packageInfo, r.token, displayId, r.overrideConfig);
         appContext.setOuterContext(activity);
         Context baseContext = appContext;
 
@@ -3481,14 +3466,9 @@
             if (!r.activity.mFinished && willBeVisible
                     && r.activity.mDecor != null && !r.hideForNow) {
                 if (r.newConfig != null) {
-                    r.tmpConfig.setTo(r.newConfig);
-                    if (r.overrideConfig != null) {
-                        r.tmpConfig.updateFrom(r.overrideConfig);
-                    }
+                    performConfigurationChangedForActivity(r, r.newConfig, REPORT_TO_ACTIVITY);
                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
-                            + r.activityInfo.name + " with newConfig " + r.tmpConfig);
-                    performConfigurationChanged(r.activity, r.tmpConfig, REPORT_TO_ACTIVITY);
-                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
+                            + r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig);
                     r.newConfig = null;
                 }
                 if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
@@ -3722,10 +3702,9 @@
             } catch (RemoteException ex) {
                 if (ex instanceof TransactionTooLargeException
                         && activity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) {
-                    Log.e(TAG, "App tried sending too much data in instance state", ex);
+                    Log.e(TAG, "App sent too much data in instance state, so it was ignored", ex);
                     return;
                 }
-
                 throw ex.rethrowFromSystemServer();
             }
         }
@@ -3834,14 +3813,10 @@
                     }
                 }
                 if (r.newConfig != null) {
-                    r.tmpConfig.setTo(r.newConfig);
-                    if (r.overrideConfig != null) {
-                        r.tmpConfig.updateFrom(r.overrideConfig);
-                    }
+                    performConfigurationChangedForActivity(r, r.newConfig, REPORT_TO_ACTIVITY);
                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
-                            + r.activityInfo.name + " with new config " + r.tmpConfig);
-                    performConfigurationChanged(r.activity, r.tmpConfig, REPORT_TO_ACTIVITY);
-                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
+                            + r.activityInfo.name + " with new config "
+                            + r.activity.mCurrentConfig);
                     r.newConfig = null;
                 }
             } else {
@@ -4546,8 +4521,44 @@
         return callbacks;
     }
 
-    private static void performConfigurationChanged(ComponentCallbacks2 cb, Configuration config,
-            boolean reportToActivity) {
+    /**
+     * Updates the configuration for an Activity. The ActivityClientRecord's
+     * {@link ActivityClientRecord#overrideConfig} is used to compute the final Configuration for
+     * that Activity. {@link ActivityClientRecord#tmpConfig} is used as a temporary for delivering
+     * the updated Configuration.
+     * @param r ActivityClientRecord representing the Activity.
+     * @param newBaseConfig The new configuration to use. This may be augmented with
+     *                      {@link ActivityClientRecord#overrideConfig}.
+     * @param reportToActivity true if the change should be reported to the Activity's callback.
+     */
+    private void performConfigurationChangedForActivity(ActivityClientRecord r,
+                                                        Configuration newBaseConfig,
+                                                        boolean reportToActivity) {
+        r.tmpConfig.setTo(newBaseConfig);
+        if (r.overrideConfig != null) {
+            r.tmpConfig.updateFrom(r.overrideConfig);
+        }
+        performConfigurationChanged(r.activity, r.token, r.tmpConfig, r.overrideConfig,
+                reportToActivity);
+        freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
+    }
+
+    /**
+     * Decides whether to update an Activity's configuration and whether to tell the
+     * Activity/Component about it.
+     * @param cb The component callback to notify of configuration change.
+     * @param activityToken The Activity binder token for which this configuration change happened.
+     *                      If the change is global, this is null.
+     * @param newConfig The new configuration.
+     * @param overrideConfig The override config that differentiates the Activity's configuration
+     *                       from the base global configuration.
+     * @param reportToActivity Notify the Activity of the change.
+     */
+    private void performConfigurationChanged(ComponentCallbacks2 cb,
+                                             IBinder activityToken,
+                                             Configuration newConfig,
+                                             Configuration overrideConfig,
+                                             boolean reportToActivity) {
         // Only for Activity objects, check that they actually call up to their
         // superclass implementation.  ComponentCallbacks2 is an interface, so
         // we check the runtime type and act accordingly.
@@ -4564,7 +4575,7 @@
             // If the new config is the same as the config this Activity
             // is already running with then don't bother calling
             // onConfigurationChanged
-            int diff = activity.mCurrentConfig.diff(config);
+            int diff = activity.mCurrentConfig.diff(newConfig);
             if (diff != 0) {
                 // If this activity doesn't handle any of the config changes then don't bother
                 // calling onConfigurationChanged as we're going to destroy it.
@@ -4579,21 +4590,31 @@
             }
         }
 
-        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb
-                + ": shouldChangeConfig=" + shouldChangeConfig);
+        if (DEBUG_CONFIGURATION) {
+            Slog.v(TAG, "Config callback " + cb + ": shouldChangeConfig=" + shouldChangeConfig);
+        }
+
         if (shouldChangeConfig) {
+            if (activityToken != null) {
+                // We only update an Activity's configuration if this is not a global
+                // configuration change. This must also be done before the callback,
+                // or else we violate the contract that the new resources are available
+                // in {@link ComponentCallbacks2#onConfigurationChanged(Configuration)}.
+                mResourcesManager.updateResourcesForActivity(activityToken, overrideConfig);
+            }
+
             if (reportToActivity) {
-                cb.onConfigurationChanged(config);
+                cb.onConfigurationChanged(newConfig);
             }
 
             if (activity != null) {
                 if (reportToActivity && !activity.mCalled) {
                     throw new SuperNotCalledException(
                             "Activity " + activity.getLocalClassName() +
-                        " did not call through to super.onConfigurationChanged()");
+                            " did not call through to super.onConfigurationChanged()");
                 }
                 activity.mConfigChangeFlags = 0;
-                activity.mCurrentConfig = new Configuration(config);
+                activity.mCurrentConfig = new Configuration(newConfig);
             }
         }
     }
@@ -4610,7 +4631,8 @@
             mCompatConfiguration = new Configuration();
         }
         mCompatConfiguration.setTo(mConfiguration);
-        if (mResourcesManager.applyCompatConfiguration(displayDensity, mCompatConfiguration)) {
+        if (mResourcesManager.applyCompatConfigurationLocked(displayDensity,
+                mCompatConfiguration)) {
             config = mCompatConfiguration;
         }
         return config;
@@ -4662,7 +4684,8 @@
         if (callbacks != null) {
             final int N = callbacks.size();
             for (int i=0; i<N; i++) {
-                performConfigurationChanged(callbacks.get(i), config, REPORT_TO_ACTIVITY);
+                performConfigurationChanged(callbacks.get(i), null, config, null,
+                        REPORT_TO_ACTIVITY);
             }
         }
     }
@@ -4688,15 +4711,8 @@
         if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
                 + r.activityInfo.name + ", with callback=" + reportToActivity);
 
-        r.tmpConfig.setTo(mCompatConfiguration);
-        if (data.overrideConfig != null) {
-            r.overrideConfig = data.overrideConfig;
-            r.tmpConfig.updateFrom(data.overrideConfig);
-        }
-        performConfigurationChanged(r.activity, r.tmpConfig, reportToActivity);
-
-        freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(mCompatConfiguration));
-
+        r.overrideConfig = data.overrideConfig;
+        performConfigurationChangedForActivity(r, mCompatConfiguration, reportToActivity);
         mSomeActivitiesChanged = true;
     }
 
@@ -5033,21 +5049,25 @@
          */
         TimeZone.setDefault(null);
 
-        /*
-         * Initialize the default locales in this process for the reasons we set the time zone.
-         *
-         * We do this through ResourcesManager, since we need to do locale negotiation.
-         */
-        mResourcesManager.setDefaultLocalesLocked(data.config.getLocales());
+        synchronized (mResourcesManager) {
+            /*
+             * Initialize the default locales in this process for the reasons we set the time zone.
+             *
+             * We do this through ResourcesManager, since we need to do locale negotiation.
+             */
+            mResourcesManager.setDefaultLocalesLocked(data.config.getLocales());
 
-        /*
-         * Update the system configuration since its preloaded and might not
-         * reflect configuration changes. The configuration object passed
-         * in AppBindData can be safely assumed to be up to date
-         */
-        mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
-        mCurDefaultDisplayDpi = data.config.densityDpi;
-        applyCompatConfiguration(mCurDefaultDisplayDpi);
+            /*
+             * Update the system configuration since its preloaded and might not
+             * reflect configuration changes. The configuration object passed
+             * in AppBindData can be safely assumed to be up to date
+             */
+            mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
+            mCurDefaultDisplayDpi = data.config.densityDpi;
+
+            // This calls mResourcesManager so keep it within the synchronized block.
+            applyCompatConfiguration(mCurDefaultDisplayDpi);
+        }
 
         data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
 
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 455f869..b08142a 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -985,11 +985,16 @@
     /**
      * Gets information about the next alarm clock currently scheduled.
      *
-     * The alarm clocks considered are those scheduled by {@link #setAlarmClock}
-     * from any package of the calling user.
+     * The alarm clocks considered are those scheduled by any application
+     * using the {@link #setAlarmClock} method.
+     *
+     * @return An {@link AlarmClockInfo} object describing the next upcoming alarm
+     *   clock event that will occur.  If there are no alarm clock events currently
+     *   scheduled, this method will return {@code null}.
      *
      * @see #setAlarmClock
      * @see AlarmClockInfo
+     * @see #ACTION_NEXT_ALARM_CLOCK_CHANGED
      */
     public AlarmClockInfo getNextAlarmClock() {
         return getNextAlarmClock(UserHandle.myUserId());
@@ -998,11 +1003,16 @@
     /**
      * Gets information about the next alarm clock currently scheduled.
      *
-     * The alarm clocks considered are those scheduled by {@link #setAlarmClock}
-     * from any package of the given {@parm userId}.
+     * The alarm clocks considered are those scheduled by any application
+     * using the {@link #setAlarmClock} method within the given user.
+     *
+     * @return An {@link AlarmClockInfo} object describing the next upcoming alarm
+     *   clock event that will occur within the given user.  If there are no alarm clock
+     *   events currently scheduled in that user, this method will return {@code null}.
      *
      * @see #setAlarmClock
      * @see AlarmClockInfo
+     * @see #ACTION_NEXT_ALARM_CLOCK_CHANGED
      *
      * @hide
      */
@@ -1015,7 +1025,7 @@
     }
 
     /**
-     * An immutable description of an alarm clock.
+     * An immutable description of a scheduled "alarm clock" event.
      *
      * @see AlarmManager#setAlarmClock
      * @see AlarmManager#getNextAlarmClock
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 82c4c51..64586a6 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1267,8 +1267,15 @@
 
     /** @hide */
     public void setUserRestriction(int code, boolean restricted, IBinder token) {
+        setUserRestriction(code, restricted, token, /*exceptionPackages*/null);
+    }
+
+    /** @hide */
+    public void setUserRestriction(int code, boolean restricted, IBinder token,
+            String[] exceptionPackages) {
         try {
-            mService.setUserRestriction(code, restricted, token, mContext.getUserId());
+            mService.setUserRestriction(code, restricted, token, mContext.getUserId(),
+                  exceptionPackages);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 0b44925..5ef03d1 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1147,7 +1147,7 @@
     }
 
     private Drawable getManagedProfileIconForDensity(UserHandle user, int drawableId, int density) {
-        UserInfo userInfo = getUserIfProfile(user.getIdentifier());
+        UserInfo userInfo = getUserInfo(user.getIdentifier());
         if (userInfo != null && userInfo.isManagedProfile()) {
             return getDrawableForDensity(drawableId, density);
         }
@@ -1156,7 +1156,7 @@
 
     @Override
     public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
-        UserInfo userInfo = getUserIfProfile(user.getIdentifier());
+        UserInfo userInfo = getUserInfo(user.getIdentifier());
         if (userInfo != null && userInfo.isManagedProfile()) {
             return Resources.getSystem().getString(
                     com.android.internal.R.string.managed_profile_label_badge, label);
@@ -1182,7 +1182,7 @@
                 sameUid ? app.sourceDir : app.publicSourceDir,
                 sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs,
                 app.resourceDirs, app.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
-                null, mContext.mPackageInfo);
+                mContext.mPackageInfo);
         if (r != null) {
             return r;
         }
@@ -2025,6 +2025,15 @@
     }
 
     @Override
+    public void flushPackageRestrictionsAsUser(int userId) {
+        try {
+            mPM.flushPackageRestrictionsAsUser(userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @Override
     public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
             UserHandle user) {
         try {
@@ -2252,21 +2261,15 @@
 
     private int getBadgeResIdForUser(int userHandle) {
         // Return the framework-provided badge.
-        UserInfo userInfo = getUserIfProfile(userHandle);
+        UserInfo userInfo = getUserInfo(userHandle);
         if (userInfo != null && userInfo.isManagedProfile()) {
             return com.android.internal.R.drawable.ic_corp_icon_badge;
         }
         return 0;
     }
 
-    private UserInfo getUserIfProfile(int userHandle) {
-        List<UserInfo> userProfiles = getUserManager().getProfiles(mContext.getUserId());
-        for (UserInfo user : userProfiles) {
-            if (user.id == userHandle) {
-                return user;
-            }
-        }
-        return null;
+    private UserInfo getUserInfo(int userHandle) {
+        return getUserManager().getUserInfo(userHandle);
     }
 
     /** {@hide} */
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index e76f991..4fccbc9 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1332,9 +1332,14 @@
             }
         }
         try {
-            return ActivityManagerNative.getDefault().registerReceiver(
+            final Intent intent = ActivityManagerNative.getDefault().registerReceiver(
                     mMainThread.getApplicationThread(), mBasePackageName,
                     rd, filter, broadcastPermission, userId);
+            if (intent != null) {
+                intent.setExtrasClassLoader(getClassLoader());
+                intent.prepareToEnterProcess();
+            }
+            return intent;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1994,9 +1999,10 @@
     }
 
     static ContextImpl createActivityContext(ActivityThread mainThread,
-            LoadedApk packageInfo, int displayId, Configuration overrideConfiguration) {
+            LoadedApk packageInfo, IBinder activityToken, int displayId,
+            Configuration overrideConfiguration) {
         if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
-        return new ContextImpl(null, mainThread, packageInfo, null, null, 0,
+        return new ContextImpl(null, mainThread, packageInfo, activityToken, null, 0,
                 null, overrideConfiguration, displayId);
     }
 
@@ -2054,10 +2060,16 @@
                     || overrideConfiguration != null
                     || (compatInfo != null && compatInfo.applicationScale
                             != resources.getCompatibilityInfo().applicationScale)) {
-                resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(),
-                        packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(),
-                        packageInfo.getApplicationInfo().sharedLibraryFiles, displayId,
-                        overrideConfiguration, compatInfo, packageInfo.getClassLoader());
+                resources = mResourcesManager.getResources(
+                        activityToken,
+                        packageInfo.getResDir(),
+                        packageInfo.getSplitResDirs(),
+                        packageInfo.getOverlayDirs(),
+                        packageInfo.getApplicationInfo().sharedLibraryFiles,
+                        displayId,
+                        overrideConfiguration,
+                        compatInfo,
+                        packageInfo.getClassLoader());
             }
         }
         mResources = resources;
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index eadf497..8e87e26 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -151,6 +151,12 @@
             boolean preserveWindows, boolean animate) throws RemoteException;
 
     /**
+     * Moves all tasks from the docked stack in the fullscreen stack and puts the top task of the
+     * fullscreen stack into the docked stack.
+     */
+    public void swapDockedAndFullscreenStack() throws RemoteException;
+
+    /**
      * Resizes the docked stack, and all other stacks as the result of the dock stack bounds change.
      *
      * @param dockedBounds The bounds for the docked stack.
@@ -469,8 +475,13 @@
 
     public void keyguardWaitingForActivityDrawn() throws RemoteException;
 
-    public void keyguardGoingAway(boolean disableWindowAnimations,
-            boolean keyguardGoingToNotificationShade) throws RemoteException;
+    /**
+     * Notify the system that the keyguard is going away.
+     *
+     * @param flags See {@link android.view.WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
+     *              etc.
+     */
+    public void keyguardGoingAway(int flags) throws RemoteException;
 
     public boolean shouldUpRecreateTask(IBinder token, String destAffinity)
             throws RemoteException;
@@ -998,4 +1009,5 @@
     int GET_MEMORY_TRIM_LEVEL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+369;
     int RESIZE_PINNED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 370;
     int IS_VR_PACKAGE_ENABLED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 371;
+    int SWAP_DOCKED_AND_FULLSCREEN_STACK = IBinder.FIRST_CALL_TRANSACTION + 372;
 }
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index cd17078..c68fd65 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -281,11 +281,11 @@
             addedPaths.addAll(newPaths);
         }
         synchronized (this) {
-            mClassLoader = createOrUpdateClassLoaderLocked(addedPaths);
+            createOrUpdateClassLoaderLocked(addedPaths);
             if (mResources != null) {
-                mResources = mActivityThread.getNewTopLevelResources(mResDir, mSplitResDirs,
+                mResources = mActivityThread.getTopLevelResources(mResDir, mSplitResDirs,
                         mOverlayDirs, mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
-                        null /*overrideConfiguration*/, this);
+                        this);
             }
         }
     }
@@ -402,101 +402,99 @@
                 }
             }
         }
-
-        final String zip = TextUtils.join(File.pathSeparator, outZipPaths);
     }
 
-    private ClassLoader createOrUpdateClassLoaderLocked(List<String> addedPaths) {
-        final ClassLoader classLoader;
-        if (mIncludeCode && !mPackageName.equals("android")) {
-            // Avoid the binder call when the package is the current application package.
-            // The activity manager will perform ensure that dexopt is performed before
-            // spinning up the process.
-            if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
-                VMRuntime.getRuntime().vmInstructionSet();
-                try {
-                    ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
-                } catch (RemoteException re) {
-                    throw re.rethrowFromSystemServer();
-                }
+    private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
+        if (mPackageName.equals("android")) {
+            if (mClassLoader != null) {
+                // nothing to update
+                return;
             }
 
-            final List<String> zipPaths = new ArrayList<>();
-            final List<String> libPaths = new ArrayList<>();
-
-            if (mRegisterPackage) {
-                try {
-                    ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                }
-            }
-
-            makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths);
-            final String zip = TextUtils.join(File.pathSeparator, zipPaths);
-            final boolean isBundledApp = mApplicationInfo.isSystemApp()
-                    && !mApplicationInfo.isUpdatedSystemApp();
-            String libraryPermittedPath = mDataDir;
-            if (isBundledApp) {
-                // This is necessary to grant bundled apps access to
-                // libraries located in subdirectories of /system/lib
-                libraryPermittedPath += File.pathSeparator +
-                                        System.getProperty("java.library.path");
-            }
-            // DO NOT SHIP: this is a workaround for apps loading native libraries
-            // provided by 3rd party apps using absolute path instead of corresponding
-            // classloader; see http://b/26954419 for example.
-            if (mApplicationInfo.targetSdkVersion <= 23) {
-                libraryPermittedPath += File.pathSeparator + "/data/app";
-            }
-            // -----------------------------------------------------------------------------
-
-            final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
-
-            /*
-             * With all the combination done (if necessary, actually
-             * create the class loader.
-             */
-
-            if (ActivityThread.localLOGV)
-                Slog.v(ActivityThread.TAG, "Class path: " + zip +
-                        ", JNI path: " + librarySearchPath);
-
-            if (mClassLoader == null) {
-                // Temporarily disable logging of disk reads on the Looper thread
-                // as this is early and necessary.
-                StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
-
-                classLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
-                        mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
-                        libraryPermittedPath, mBaseClassLoader);
-
-                StrictMode.setThreadPolicy(oldPolicy);
-            } else if (addedPaths != null && addedPaths.size() > 0) {
-                final String add = TextUtils.join(File.pathSeparator, addedPaths);
-                ApplicationLoaders.getDefault().addPath(mClassLoader, add);
-                classLoader = mClassLoader;
+            if (mBaseClassLoader != null) {
+                mClassLoader = mBaseClassLoader;
             } else {
-                classLoader = mClassLoader;
+                mClassLoader = ClassLoader.getSystemClassLoader();
             }
-        } else {
-            if (mClassLoader == null) {
-                if (mBaseClassLoader == null) {
-                    classLoader = ClassLoader.getSystemClassLoader();
-                } else {
-                    classLoader = mBaseClassLoader;
-                }
-            } else {
-                classLoader = mClassLoader;
+
+            return;
+        }
+
+        // Avoid the binder call when the package is the current application package.
+        // The activity manager will perform ensure that dexopt is performed before
+        // spinning up the process.
+        if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
+            VMRuntime.getRuntime().vmInstructionSet();
+            try {
+                ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
             }
         }
-        return classLoader;
+
+        final List<String> zipPaths = new ArrayList<>();
+        final List<String> libPaths = new ArrayList<>();
+
+        if (mRegisterPackage) {
+            try {
+                ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths);
+        final String zip = mIncludeCode ? TextUtils.join(File.pathSeparator, zipPaths) : "";
+        final boolean isBundledApp = mApplicationInfo.isSystemApp()
+                && !mApplicationInfo.isUpdatedSystemApp();
+        String libraryPermittedPath = mDataDir;
+        if (isBundledApp) {
+            // This is necessary to grant bundled apps access to
+            // libraries located in subdirectories of /system/lib
+            libraryPermittedPath += File.pathSeparator +
+                                    System.getProperty("java.library.path");
+        }
+        // DO NOT SHIP: this is a workaround for apps loading native libraries
+        // provided by 3rd party apps using absolute path instead of corresponding
+        // classloader; see http://b/26954419 for example.
+        if (mApplicationInfo.targetSdkVersion <= 23) {
+            libraryPermittedPath += File.pathSeparator + "/data/app";
+        }
+        // -----------------------------------------------------------------------------
+
+        final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
+
+        /*
+         * With all the combination done (if necessary, actually
+         * create the class loader.
+         */
+
+        if (ActivityThread.localLOGV)
+            Slog.v(ActivityThread.TAG, "Class path: " + zip +
+                    ", JNI path: " + librarySearchPath);
+
+        if (mClassLoader == null) {
+            // Temporarily disable logging of disk reads on the Looper thread
+            // as this is early and necessary.
+            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+
+            mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
+                    mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
+                    libraryPermittedPath, mBaseClassLoader);
+
+            StrictMode.setThreadPolicy(oldPolicy);
+        }
+
+        if (addedPaths != null && addedPaths.size() > 0) {
+            final String add = TextUtils.join(File.pathSeparator, addedPaths);
+            ApplicationLoaders.getDefault().addPath(mClassLoader, add);
+        }
     }
 
     public ClassLoader getClassLoader() {
         synchronized (this) {
             if (mClassLoader == null) {
-                mClassLoader = createOrUpdateClassLoaderLocked(null /*addedPaths*/);
+                createOrUpdateClassLoaderLocked(null /*addedPaths*/);
             }
             return mClassLoader;
         }
@@ -668,7 +666,7 @@
     public Resources getResources(ActivityThread mainThread) {
         if (mResources == null) {
             mResources = mainThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs,
-                    mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this);
+                    mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, this);
         }
         return mResources;
     }
@@ -915,6 +913,8 @@
                 mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
                 mStrongRef = strong ? rd : null;
             }
+
+            @Override
             public void performReceive(Intent intent, int resultCode, String data,
                     Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                 LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
@@ -998,6 +998,7 @@
                 try {
                     ClassLoader cl =  mReceiver.getClass().getClassLoader();
                     intent.setExtrasClassLoader(cl);
+                    intent.prepareToEnterProcess();
                     setExtrasClassLoader(cl);
                     receiver.setPendingResult(this);
                     receiver.onReceive(mContext, intent);
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
index 181c907..70a5e15 100644
--- a/core/java/android/app/MediaRouteButton.java
+++ b/core/java/android/app/MediaRouteButton.java
@@ -19,6 +19,7 @@
 import com.android.internal.R;
 import com.android.internal.app.MediaRouteDialogPresenter;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.res.TypedArray;
@@ -279,7 +280,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return super.verifyDrawable(who) || who == mRemoteIndicator;
     }
 
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index a2cc6b1..132b6dd 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3173,16 +3173,9 @@
         }
 
         private void bindHeaderAppName(RemoteViews contentView) {
-            PackageManager packageManager = mContext.getPackageManager();
-            ApplicationInfo info = null;
-            try {
-                info = packageManager.getApplicationInfo(mContext.getApplicationInfo().packageName,
-                        0);
-            } catch (final NameNotFoundException e) {
-                return;
-            }
-            CharSequence appName = info != null ? packageManager.getApplicationLabel(info)
-                    : null;
+            CharSequence appName = mContext.getPackageManager()
+                    .getApplicationLabel(mContext.getApplicationInfo());
+
             if (TextUtils.isEmpty(appName)) {
                 return;
             }
@@ -4222,7 +4215,8 @@
             int i=0;
             final float density = mBuilder.mContext.getResources().getDisplayMetrics().density;
             int topPadding = (int) (5 * density);
-            int bottomPadding = (int) (13 * density);
+            int bottomPadding = mBuilder.mContext.getResources().getDimensionPixelSize(
+                    com.android.internal.R.dimen.notification_content_margin_bottom);
             boolean first = true;
             while (i < mTexts.size() && i < rowIds.length) {
                 CharSequence str = mTexts.get(i);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 10aa7eb..0d4729d 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -913,10 +913,6 @@
      * (e.g. via sound &amp; vibration) and is applied globally.
      * @return One of the INTERRUPTION_FILTER_ constants, or INTERRUPTION_FILTER_UNKNOWN when
      * unavailable.
-     *
-     * <p>
-     * Only available if policy access is granted to this package.
-     * See {@link #isNotificationPolicyAccessGranted}.
      */
     public final @InterruptionFilter int getCurrentInterruptionFilter() {
         final INotificationManager service = getService();
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index bc44553d..54d813d 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -18,6 +18,8 @@
 
 import static android.app.ActivityThread.DEBUG_CONFIGURATION;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.pm.ActivityInfo;
 import android.content.res.AssetManager;
 import android.content.res.CompatibilityInfo;
@@ -26,6 +28,7 @@
 import android.content.res.ResourcesImpl;
 import android.content.res.ResourcesKey;
 import android.hardware.display.DisplayManagerGlobal;
+import android.os.IBinder;
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
 import android.util.LocaleList;
@@ -34,11 +37,16 @@
 import android.util.Slog;
 import android.view.Display;
 import android.view.DisplayAdjustments;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
 
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.List;
+import java.util.Objects;
+import java.util.WeakHashMap;
+import java.util.function.Predicate;
 
 /** @hide */
 public class ResourcesManager {
@@ -46,18 +54,56 @@
     private static final boolean DEBUG = false;
 
     private static ResourcesManager sResourcesManager;
-    private final ArrayMap<ResourcesKey, WeakReference<Resources>> mActiveResources =
-            new ArrayMap<>();
-    private final ArrayMap<Pair<Integer, DisplayAdjustments>, WeakReference<Display>> mDisplays =
-            new ArrayMap<>();
+
+    /**
+     * Predicate that returns true if a WeakReference is gc'ed.
+     */
+    private static final Predicate<WeakReference<Resources>> sEmptyReferencePredicate =
+            new Predicate<WeakReference<Resources>>() {
+                @Override
+                public boolean test(WeakReference<Resources> weakRef) {
+                    return weakRef == null || weakRef.get() == null;
+                }
+            };
 
     private String[] mSystemLocales = {};
-    private final HashSet<String> mNonSystemLocales = new HashSet<String>();
+    private final HashSet<String> mNonSystemLocales = new HashSet<>();
     private boolean mHasNonSystemLocales = false;
 
-    CompatibilityInfo mResCompatibilityInfo;
+    /**
+     * The global compatibility settings.
+     */
+    private CompatibilityInfo mResCompatibilityInfo;
 
-    Configuration mResConfiguration;
+    /**
+     * The global configuration upon which all Resources are based. Multi-window Resources
+     * apply their overrides to this configuration.
+     */
+    private final Configuration mResConfiguration = new Configuration();
+
+    /**
+     * A mapping of ResourceImpls and their configurations. These are heavy weight objects
+     * which should be reused as much as possible.
+     */
+    private final ArrayMap<ResourcesKey, WeakReference<ResourcesImpl>> mResourceImpls =
+            new ArrayMap<>();
+
+    /**
+     * A list of Resource references that can be reused.
+     */
+    private final ArrayList<WeakReference<Resources>> mResourceReferences = new ArrayList<>();
+
+    /**
+     * Each Activity may have only one Resources object.
+     */
+    private final WeakHashMap<IBinder, WeakReference<Resources>> mActivityResourceReferences =
+            new WeakHashMap<>();
+
+    /**
+     * A cache of DisplayId to DisplayAdjustments.
+     */
+    private final ArrayMap<Pair<Integer, DisplayAdjustments>, WeakReference<Display>> mDisplays =
+            new ArrayMap<>();
 
     public static ResourcesManager getInstance() {
         synchronized (ResourcesManager.class) {
@@ -76,7 +122,11 @@
         return getDisplayMetricsLocked(Display.DEFAULT_DISPLAY);
     }
 
-    DisplayMetrics getDisplayMetricsLocked(int displayId) {
+    /**
+     * Protected so that tests can override and returns something a fixed value.
+     */
+    @VisibleForTesting
+    protected DisplayMetrics getDisplayMetricsLocked(int displayId) {
         DisplayMetrics dm = new DisplayMetrics();
         final Display display =
                 getAdjustedDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
@@ -88,12 +138,12 @@
         return dm;
     }
 
-    final void applyNonDefaultDisplayMetricsToConfigurationLocked(
-            DisplayMetrics dm, Configuration config) {
+    private static void applyNonDefaultDisplayMetricsToConfiguration(
+            @NonNull DisplayMetrics dm, @NonNull Configuration config) {
         config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
         config.densityDpi = dm.densityDpi;
-        config.screenWidthDp = (int)(dm.widthPixels / dm.density);
-        config.screenHeightDp = (int)(dm.heightPixels / dm.density);
+        config.screenWidthDp = (int) (dm.widthPixels / dm.density);
+        config.screenHeightDp = (int) (dm.heightPixels / dm.density);
         int sl = Configuration.resetScreenLayout(config.screenLayout);
         if (dm.widthPixels > dm.heightPixels) {
             config.orientation = Configuration.ORIENTATION_LANDSCAPE;
@@ -110,8 +160,8 @@
         config.compatSmallestScreenWidthDp = config.smallestScreenWidthDp;
     }
 
-    public boolean applyCompatConfiguration(int displayDensity,
-            Configuration compatConfiguration) {
+    public boolean applyCompatConfigurationLocked(int displayDensity,
+            @NonNull Configuration compatConfiguration) {
         if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) {
             mResCompatibilityInfo.applyToConfiguration(displayDensity, compatConfiguration);
             return true;
@@ -126,7 +176,8 @@
      * @param displayId display Id.
      * @param displayAdjustments display adjustments.
      */
-    public Display getAdjustedDisplay(final int displayId, DisplayAdjustments displayAdjustments) {
+    public Display getAdjustedDisplay(final int displayId,
+            @Nullable DisplayAdjustments displayAdjustments) {
         final DisplayAdjustments displayAdjustmentsCopy = (displayAdjustments != null)
                 ? new DisplayAdjustments(displayAdjustments) : new DisplayAdjustments();
         final Pair<Integer, DisplayAdjustments> key =
@@ -153,76 +204,42 @@
     }
 
     /**
-     * Creates the top level Resources for applications with the given compatibility info.
+     * Creates an AssetManager from the paths within the ResourcesKey.
      *
-     * @param resDir the resource directory.
-     * @param splitResDirs split resource directories.
-     * @param overlayDirs the resource overlay directories.
-     * @param libDirs the shared library resource dirs this app references.
-     * @param displayId display Id.
-     * @param overrideConfiguration override configurations.
-     * @param compatInfo the compatibility info. Must not be null.
-     * @param classLoader the class loader for the resource package
-     */
-    Resources getTopLevelResources(String resDir, String[] splitResDirs,
-            String[] overlayDirs, String[] libDirs, int displayId,
-            Configuration overrideConfiguration, CompatibilityInfo compatInfo,
-            ClassLoader classLoader) {
-        final float scale = compatInfo.applicationScale;
-        Configuration overrideConfigCopy = (overrideConfiguration != null)
-                ? new Configuration(overrideConfiguration) : null;
-        ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfigCopy, scale);
-        Resources r;
-        final boolean findSystemLocales;
-        final boolean hasNonSystemLocales;
-        synchronized (this) {
-            // Resources is app scale dependent.
-            if (DEBUG) Slog.w(TAG, "getTopLevelResources: " + resDir + " / " + scale);
-
-            WeakReference<Resources> wr = mActiveResources.get(key);
-            r = wr != null ? wr.get() : null;
-            //if (r != null) Log.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
-            if (r != null && r.getAssets().isUpToDate()) {
-                if (DEBUG) Slog.w(TAG, "Returning cached resources " + r + " " + resDir
-                        + ": appScale=" + r.getCompatibilityInfo().applicationScale
-                        + " key=" + key + " overrideConfig=" + overrideConfiguration);
-                return r;
-            }
-            findSystemLocales = (mSystemLocales.length == 0);
-            hasNonSystemLocales = mHasNonSystemLocales;
-        }
-
-        //if (r != null) {
-        //    Log.w(TAG, "Throwing away out-of-date resources!!!! "
-        //            + r + " " + resDir);
-        //}
-
+     * This can be overridden in tests so as to avoid creating a real AssetManager with
+     * real APK paths.
+     * @param key The key containing the resource paths to add to the AssetManager.
+     * @return a new AssetManager.
+    */
+    @VisibleForTesting
+    protected AssetManager createAssetManager(@NonNull final ResourcesKey key) {
         AssetManager assets = new AssetManager();
+
         // resDir can be null if the 'android' package is creating a new Resources object.
         // This is fine, since each AssetManager automatically loads the 'android' package
         // already.
-        if (resDir != null) {
-            if (assets.addAssetPath(resDir) == 0) {
+        if (key.mResDir != null) {
+            if (assets.addAssetPath(key.mResDir) == 0) {
                 return null;
             }
         }
 
-        if (splitResDirs != null) {
-            for (String splitResDir : splitResDirs) {
+        if (key.mSplitResDirs != null) {
+            for (final String splitResDir : key.mSplitResDirs) {
                 if (assets.addAssetPath(splitResDir) == 0) {
                     return null;
                 }
             }
         }
 
-        if (overlayDirs != null) {
-            for (String idmapPath : overlayDirs) {
+        if (key.mOverlayDirs != null) {
+            for (final String idmapPath : key.mOverlayDirs) {
                 assets.addOverlayPath(idmapPath);
             }
         }
 
-        if (libDirs != null) {
-            for (String libDir : libDirs) {
+        if (key.mLibDirs != null) {
+            for (final String libDir : key.mLibDirs) {
                 if (libDir.endsWith(".apk")) {
                     // Avoid opening files we know do not have resources,
                     // like code-only .jar files.
@@ -233,16 +250,17 @@
                 }
             }
         }
+        return assets;
+    }
 
-        //Log.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
-        DisplayMetrics dm = getDisplayMetricsLocked(displayId);
+    private Configuration generateConfig(@NonNull ResourcesKey key, @NonNull DisplayMetrics dm) {
         Configuration config;
-        final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+        final boolean isDefaultDisplay = (key.mDisplayId == Display.DEFAULT_DISPLAY);
         final boolean hasOverrideConfig = key.hasOverrideConfiguration();
         if (!isDefaultDisplay || hasOverrideConfig) {
             config = new Configuration(getConfiguration());
             if (!isDefaultDisplay) {
-                applyNonDefaultDisplayMetricsToConfigurationLocked(dm, config);
+                applyNonDefaultDisplayMetricsToConfiguration(dm, config);
             }
             if (hasOverrideConfig) {
                 config.updateFrom(key.mOverrideConfiguration);
@@ -251,16 +269,212 @@
         } else {
             config = getConfiguration();
         }
-        r = new Resources(classLoader);
-        r.setImpl(new ResourcesImpl(assets, dm, config, compatInfo));
-        if (DEBUG) Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
-                + r.getConfiguration() + " appScale=" + r.getCompatibilityInfo().applicationScale);
+        return config;
+    }
 
-        final String[] systemLocales = (
-                findSystemLocales ?
-                AssetManager.getSystem().getLocales() :
-                null);
-        final String[] nonSystemLocales = assets.getNonSystemLocales();
+
+    private ResourcesImpl createResourcesImpl(@NonNull ResourcesKey key) {
+        AssetManager assets = createAssetManager(key);
+        DisplayMetrics dm = getDisplayMetricsLocked(key.mDisplayId);
+        Configuration config = generateConfig(key, dm);
+        ResourcesImpl impl = new ResourcesImpl(assets, dm, config, key.mCompatInfo);
+        if (DEBUG) {
+            Slog.d(TAG, "- creating impl=" + impl + " with key: " + key);
+        }
+        return impl;
+    }
+
+    /**
+     * Finds a cached ResourcesImpl object that matches the given ResourcesKey.
+     *
+     * @param key The key to match.
+     * @return a ResourcesImpl if the key matches a cache entry, null otherwise.
+     */
+    private ResourcesImpl findResourcesImplForKey(@NonNull ResourcesKey key) {
+        WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.get(key);
+        ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
+        if (impl != null && impl.getAssets().isUpToDate()) {
+            return impl;
+        }
+        return null;
+    }
+
+    /**
+     * Find the ResourcesKey that this ResourcesImpl object is associated with.
+     * @return the ResourcesKey or null if none was found.
+     */
+    private ResourcesKey findKeyForResourceImpl(@NonNull ResourcesImpl resourceImpl) {
+        final int refCount = mResourceImpls.size();
+        for (int i = 0; i < refCount; i++) {
+            WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i);
+            ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
+            if (impl != null && resourceImpl == impl) {
+                return mResourceImpls.keyAt(i);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets an existing Resources object tied to this Activity, or creates one if it doesn't exist
+     * or the class loader is different.
+     */
+    private Resources getOrCreateResourcesForActivityLocked(@NonNull IBinder activityToken,
+            @NonNull ClassLoader classLoader, @NonNull ResourcesImpl impl) {
+        // This is a request tied to an Activity, meaning we will need to update all
+        // Activity related Resources to match this configuration.
+        WeakReference<Resources> weakResourceRef = mActivityResourceReferences.get(activityToken);
+        Resources resources = weakResourceRef != null ? weakResourceRef.get() : null;
+        if (resources == null || !Objects.equals(resources.getClassLoader(), classLoader)) {
+            resources = new Resources(classLoader);
+            mActivityResourceReferences.put(activityToken, new WeakReference<>(resources));
+            if (DEBUG) {
+                Slog.d(TAG, "- creating new ref=" + resources);
+            }
+        } else {
+            if (DEBUG) {
+                Slog.d(TAG, "- using existing ref=" + resources);
+            }
+        }
+
+        if (resources.getImpl() != impl) {
+            if (DEBUG) {
+                Slog.d(TAG, "- setting ref=" + resources + " with impl=" + impl);
+            }
+
+            // Setting an impl is expensive because we update all ThemeImpl references.
+            // too.
+            resources.setImpl(impl);
+        }
+        return resources;
+    }
+
+    /**
+     * Gets an existing Resources object if the class loader and ResourcesImpl are the same,
+     * otherwise creates a new Resources object.
+     */
+    private Resources getOrCreateResourcesLocked(@NonNull ClassLoader classLoader,
+            @NonNull ResourcesImpl impl) {
+        // Find an existing Resources that has this ResourcesImpl set.
+        final int refCount = mResourceReferences.size();
+        for (int i = 0; i < refCount; i++) {
+            WeakReference<Resources> weakResourceRef = mResourceReferences.get(i);
+            Resources resources = weakResourceRef != null ? weakResourceRef.get() : null;
+            if (resources != null &&
+                    Objects.equals(resources.getClassLoader(), classLoader) &&
+                    resources.getImpl() == impl) {
+                if (DEBUG) {
+                    Slog.d(TAG, "- using existing ref=" + resources);
+                }
+                return resources;
+            }
+        }
+
+        // Create a new Resources reference and use the existing ResourcesImpl object.
+        Resources resources = new Resources(classLoader);
+        resources.setImpl(impl);
+        mResourceReferences.add(new WeakReference<>(resources));
+        if (DEBUG) {
+            Slog.d(TAG, "- creating new ref=" + resources);
+            Slog.d(TAG, "- setting ref=" + resources + " with impl=" + impl);
+        }
+        return resources;
+    }
+
+    /**
+     * Gets or creates a new Resources object associated with the IBinder token. References returned
+     * by this method live as long as the Activity, meaning they can be cached and used by the
+     * Activity even after a configuration change. If any other parameter is changed
+     * (resDir, splitResDirs, overrideConfig) for a given Activity, the same Resources object
+     * is updated and handed back to the caller. However, changing the class loader will result in a
+     * new Resources object.
+     * <p/>
+     * If activityToken is null, a cached Resources object will be returned if it matches the
+     * input parameters. Otherwise a new Resources object that satisfies these parameters is
+     * returned.
+     *
+     * @param activityToken Represents an Activity. If null, global resources are assumed.
+     * @param resDir The base resource path. Can be null (only framework resources will be loaded).
+     * @param splitResDirs An array of split resource paths. Can be null.
+     * @param overlayDirs An array of overlay paths. Can be null.
+     * @param libDirs An array of resource library paths. Can be null.
+     * @param displayId The ID of the display for which to create the resources.
+     * @param overrideConfig The configuration to apply on top of the base configuration. Can be
+     * null. Mostly used with Activities that are in multi-window which may override width and
+     * height properties from the base config.
+     * @param compatInfo The compatibility settings to use. Cannot be null. A default to use is
+     * {@link CompatibilityInfo#DEFAULT_COMPATIBILITY_INFO}.
+     * @param classLoader The class loader to use when inflating Resources. If null, the
+     * {@link ClassLoader#getSystemClassLoader()} is used.
+     * @return a Resources object from which to access resources.
+     */
+    public Resources getResources(@Nullable IBinder activityToken,
+            @Nullable String resDir,
+            @Nullable String[] splitResDirs,
+            @Nullable String[] overlayDirs,
+            @Nullable String[] libDirs,
+            int displayId,
+            @Nullable Configuration overrideConfig,
+            @NonNull CompatibilityInfo compatInfo,
+            @Nullable ClassLoader classLoader) {
+        final ResourcesKey key = new ResourcesKey(
+                resDir,
+                splitResDirs,
+                overlayDirs,
+                libDirs,
+                displayId,
+                overrideConfig != null ? new Configuration(overrideConfig) : null, // Copy
+                compatInfo);
+
+        classLoader = classLoader != null ? classLoader : ClassLoader.getSystemClassLoader();
+
+        final boolean findSystemLocales;
+        final boolean hasNonSystemLocales;
+        synchronized (this) {
+            findSystemLocales = (mSystemLocales.length == 0);
+            hasNonSystemLocales = mHasNonSystemLocales;
+
+            if (DEBUG) {
+                Throwable here = new Throwable();
+                here.fillInStackTrace();
+                Slog.w(TAG, "!! Get resources for activity=" + activityToken + " key=" + key, here);
+            }
+
+            if (activityToken != null) {
+                ResourcesImpl resourcesImpl = findResourcesImplForKey(key);
+                if (resourcesImpl != null) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "- using existing impl=" + resourcesImpl);
+                    }
+                    return getOrCreateResourcesForActivityLocked(activityToken, classLoader,
+                            resourcesImpl);
+                }
+
+                // We will create the ResourcesImpl object outside of holding this lock.
+
+            } else {
+                // Clean up any dead references so they don't pile up.
+                ArrayUtils.unstableRemoveIf(mResourceReferences, sEmptyReferencePredicate);
+
+                // Not tied to an Activity, find a shared Resources that has the right ResourcesImpl
+                ResourcesImpl resourcesImpl = findResourcesImplForKey(key);
+                if (resourcesImpl != null) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "- using existing impl=" + resourcesImpl);
+                    }
+                    return getOrCreateResourcesLocked(classLoader, resourcesImpl);
+                }
+
+                // We will create the ResourcesImpl object outside of holding this lock.
+            }
+        }
+
+        // If we're here, we didn't find a suitable ResourcesImpl to use, so create one now.
+        ResourcesImpl resourcesImpl = createResourcesImpl(key);
+
+        final String[] systemLocales = findSystemLocales
+                ? AssetManager.getSystem().getLocales() : null;
+        final String[] nonSystemLocales = resourcesImpl.getAssets().getNonSystemLocales();
         // Avoid checking for non-pseudo-locales if we already know there were some from a previous
         // Resources. The default value (for when hasNonSystemLocales is true) doesn't matter,
         // since mHasNonSystemLocales will also be true, and thus isPseudoLocalesOnly would not be
@@ -269,41 +483,75 @@
                 LocaleList.isPseudoLocalesOnly(nonSystemLocales);
 
         synchronized (this) {
-            WeakReference<Resources> wr = mActiveResources.get(key);
-            Resources existing = wr != null ? wr.get() : null;
-            if (existing != null && existing.getAssets().isUpToDate()) {
-                // Someone else already created the resources while we were
-                // unlocked; go ahead and use theirs.
-                r.getAssets().close();
-                return existing;
-            }
-
-            // XXX need to remove entries when weak references go away
-            mActiveResources.put(key, new WeakReference<>(r));
             if (mSystemLocales.length == 0) {
                 mSystemLocales = systemLocales;
             }
             mNonSystemLocales.addAll(Arrays.asList(nonSystemLocales));
             mHasNonSystemLocales = mHasNonSystemLocales || !isPseudoLocalesOnly;
-            if (DEBUG) Slog.v(TAG, "mActiveResources.size()=" + mActiveResources.size());
-            return r;
+
+            ResourcesImpl existingResourcesImpl = findResourcesImplForKey(key);
+            if (existingResourcesImpl != null) {
+                if (DEBUG) {
+                    Slog.d(TAG, "- got beat! existing impl=" + existingResourcesImpl
+                            + " new impl=" + resourcesImpl);
+                }
+                resourcesImpl.getAssets().close();
+                resourcesImpl = existingResourcesImpl;
+            } else {
+                // Add this ResourcesImpl to the cache.
+                mResourceImpls.put(key, new WeakReference<>(resourcesImpl));
+            }
+
+            final Resources resources;
+            if (activityToken != null) {
+                resources = getOrCreateResourcesForActivityLocked(activityToken, classLoader,
+                        resourcesImpl);
+            } else {
+                resources = getOrCreateResourcesLocked(classLoader, resourcesImpl);
+            }
+            return resources;
         }
     }
 
     /**
-     * Removes the top level Resources for applications with the given compatibility info.
-     * @see #getTopLevelResources(String, String[], String[], String[], int, Configuration, CompatibilityInfo, ClassLoader)
+     * Updates an Activity's Resources object with overrideConfig. The Resources object
+     * that was previously returned by
+     * {@link #getResources(IBinder, String, String[], String[], String[], int, Configuration,
+     * CompatibilityInfo, ClassLoader)} is
+     * still valid and will have the updated configuration.
+     * @param activityToken The Activity token.
+     * @param overrideConfig The configuration override to update.
      */
-    void removeTopLevelResources(String resDir, int displayId, Configuration overrideConfiguration,
-            CompatibilityInfo compatInfo) {
-        final float scale = compatInfo.applicationScale;
-        final Configuration overrideConfigCopy = (overrideConfiguration != null)
-                ? new Configuration(overrideConfiguration) : null;
-        final ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfigCopy, scale);
-        mActiveResources.remove(key);
+    public void updateResourcesForActivity(@NonNull IBinder activityToken,
+            @Nullable Configuration overrideConfig) {
+        final ClassLoader classLoader;
+        final ResourcesKey oldKey;
+        synchronized (this) {
+            // Extract the ResourcesKey that was last used to create the Resources for this
+            // activity.
+            WeakReference<Resources> weakResRef = mActivityResourceReferences.get(activityToken);
+            final Resources resources = weakResRef != null ? weakResRef.get() : null;
+            if (resources == null) {
+                Slog.e(TAG, "can't update resources for uncached activity " + activityToken);
+                return;
+            }
+
+            classLoader = resources.getClassLoader();
+            oldKey = findKeyForResourceImpl(resources.getImpl());
+            if (oldKey == null) {
+                Slog.e(TAG, "can't find ResourcesKey for resources impl=" + resources.getImpl());
+                return;
+            }
+        }
+
+        // Update the Resources object with the new override config and all of the existing
+        // settings.
+        getResources(activityToken, oldKey.mResDir, oldKey.mSplitResDirs, oldKey.mOverlayDirs,
+                oldKey.mLibDirs, oldKey.mDisplayId, overrideConfig, oldKey.mCompatInfo,
+                classLoader);
     }
 
-    /* package */ void setDefaultLocalesLocked(LocaleList locales) {
+    /* package */ void setDefaultLocalesLocked(@NonNull LocaleList locales) {
         final int bestLocale;
         if (mHasNonSystemLocales) {
             bestLocale = locales.getFirstMatchIndexWithEnglishSupported(mNonSystemLocales);
@@ -317,11 +565,8 @@
         LocaleList.setDefault(locales, bestLocale);
     }
 
-    final boolean applyConfigurationToResourcesLocked(Configuration config,
-            CompatibilityInfo compat) {
-        if (mResConfiguration == null) {
-            mResConfiguration = new Configuration();
-        }
+    public final boolean applyConfigurationToResourcesLocked(@NonNull Configuration config,
+                                                             @Nullable CompatibilityInfo compat) {
         if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
             if (DEBUG || DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
                     + mResConfiguration.seq + ", newSeq=" + config.seq);
@@ -368,9 +613,9 @@
 
         Configuration tmpConfig = null;
 
-        for (int i = mActiveResources.size() - 1; i >= 0; i--) {
-            ResourcesKey key = mActiveResources.keyAt(i);
-            Resources r = mActiveResources.valueAt(i).get();
+        for (int i = mResourceImpls.size() - 1; i >= 0; i--) {
+            ResourcesKey key = mResourceImpls.keyAt(i);
+            ResourcesImpl r = mResourceImpls.valueAt(i).get();
             if (r != null) {
                 if (DEBUG || DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
                         + r + " config to: " + localeAdjustedConfig);
@@ -385,7 +630,7 @@
                     tmpConfig.setTo(localeAdjustedConfig);
                     if (!isDefaultDisplay) {
                         dm = getDisplayMetricsLocked(displayId);
-                        applyNonDefaultDisplayMetricsToConfigurationLocked(dm, tmpConfig);
+                        applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig);
                     }
                     if (hasOverrideConfiguration) {
                         tmpConfig.updateFrom(key.mOverrideConfiguration);
@@ -398,11 +643,10 @@
                 //        + " " + r + ": " + r.getConfiguration());
             } else {
                 //Slog.i(TAG, "Removing old resources " + v.getKey());
-                mActiveResources.removeAt(i);
+                mResourceImpls.removeAt(i);
             }
         }
 
         return changes != 0;
     }
-
-}
+}
\ No newline at end of file
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 3a5dd30..9d7f724 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -51,6 +51,7 @@
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.IHdmiControlService;
 import android.hardware.input.InputManager;
+import android.hardware.location.ContextHubManager;
 import android.hardware.usb.IUsbManager;
 import android.hardware.usb.UsbManager;
 import android.hardware.radio.RadioManager;
@@ -103,6 +104,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.Vibrator;
+import android.os.health.SystemHealthManager;
 import android.os.storage.StorageManager;
 import android.print.IPrintManager;
 import android.print.PrintManager;
@@ -273,9 +275,9 @@
             }});
 
         registerService(Context.DROPBOX_SERVICE, DropBoxManager.class,
-                new StaticServiceFetcher<DropBoxManager>() {
+                new CachedServiceFetcher<DropBoxManager>() {
             @Override
-            public DropBoxManager createService() {
+            public DropBoxManager createService(ContextImpl ctx) {
                 IBinder b = ServiceManager.getService(Context.DROPBOX_SERVICE);
                 IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
                 if (service == null) {
@@ -285,7 +287,7 @@
                     // DROPBOX_SERVICE is registered.
                     return null;
                 }
-                return new DropBoxManager(service);
+                return new DropBoxManager(ctx, service);
             }});
 
         registerService(Context.INPUT_SERVICE, InputManager.class,
@@ -747,18 +749,31 @@
             @Override
             public SoundTriggerManager createService(ContextImpl ctx) {
                 IBinder b = ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE);
-                Log.i(TAG, "Creating new instance of SoundTriggerManager object.");
                 return new SoundTriggerManager(ctx, ISoundTriggerService.Stub.asInterface(b));
             }});
 
         registerService(Context.SHORTCUT_SERVICE, ShortcutManager.class,
                 new CachedServiceFetcher<ShortcutManager>() {
-                    @Override
-                    public ShortcutManager createService(ContextImpl ctx) {
-                        IBinder b = ServiceManager.getService(Context.SHORTCUT_SERVICE);
-                        return new ShortcutManager(ctx,
-                                IShortcutService.Stub.asInterface(b));
-                    }});
+            @Override
+            public ShortcutManager createService(ContextImpl ctx) {
+                IBinder b = ServiceManager.getService(Context.SHORTCUT_SERVICE);
+                return new ShortcutManager(ctx, IShortcutService.Stub.asInterface(b));
+            }});
+
+        registerService(Context.SYSTEM_HEALTH_SERVICE, SystemHealthManager.class,
+                new CachedServiceFetcher<SystemHealthManager>() {
+            @Override
+            public SystemHealthManager createService(ContextImpl ctx) {
+                return new SystemHealthManager();
+            }});
+
+        registerService(Context.CONTEXTHUB_SERVICE, ContextHubManager.class,
+                new CachedServiceFetcher<ContextHubManager>() {
+            @Override
+            public ContextHubManager createService(ContextImpl ctx) {
+                return new ContextHubManager(ctx.getOuterContext(),
+                  ctx.mMainThread.getHandler().getLooper());
+            }});
     }
 
     /**
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 6bc03f7..52e5272 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -49,7 +49,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
-import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.WindowManagerGlobal;
@@ -263,7 +262,8 @@
 
     static class Globals extends IWallpaperManagerCallback.Stub {
         private IWallpaperManager mService;
-        private Bitmap mWallpaper;
+        private Bitmap mCachedWallpaper;
+        private int mCachedWallpaperUserId;
         private Bitmap mDefaultWallpaper;
 
         Globals(Looper looper) {
@@ -296,33 +296,34 @@
                         throw e.rethrowFromSystemServer();
                     }
                 }
-                if (mWallpaper != null) {
-                    return mWallpaper;
+                if (mCachedWallpaper != null && mCachedWallpaperUserId == userId) {
+                    return mCachedWallpaper;
                 }
-                if (mDefaultWallpaper != null) {
-                    return mDefaultWallpaper;
-                }
-                mWallpaper = null;
+                mCachedWallpaper = null;
+                mCachedWallpaperUserId = 0;
                 try {
-                    mWallpaper = getCurrentWallpaperLocked(userId);
+                    mCachedWallpaper = getCurrentWallpaperLocked(userId);
+                    mCachedWallpaperUserId = userId;
                 } catch (OutOfMemoryError e) {
                     Log.w(TAG, "No memory load current wallpaper", e);
                 }
-                if (returnDefault) {
-                    if (mWallpaper == null) {
-                        mDefaultWallpaper = getDefaultWallpaperLocked(context);
-                        return mDefaultWallpaper;
-                    } else {
-                        mDefaultWallpaper = null;
-                    }
+                if (mCachedWallpaper != null) {
+                    return mCachedWallpaper;
                 }
-                return mWallpaper;
+                if (returnDefault) {
+                    if (mDefaultWallpaper == null) {
+                        mDefaultWallpaper = getDefaultWallpaperLocked(context);
+                    }
+                    return mDefaultWallpaper;
+                }
+                return null;
             }
         }
 
         public void forgetLoadedWallpaper() {
             synchronized (this) {
-                mWallpaper = null;
+                mCachedWallpaper = null;
+                mCachedWallpaperUserId = 0;
                 mDefaultWallpaper = null;
             }
         }
@@ -918,8 +919,8 @@
      *     image for restore to a future device; {@code false} otherwise.
      * @param which Flags indicating which wallpaper(s) to configure with the new imagery.
      *
-     * @see #FLAG_SET_LOCK_WALLPAPER
-     * @see #FLAG_SET_SYSTEM_WALLPAPER
+     * @see #FLAG_SET_LOCK
+     * @see #FLAG_SET_SYSTEM
      *
      * @return An integer ID assigned to the newly active wallpaper; or zero on failure.
      *
@@ -1037,8 +1038,8 @@
      *     image for restore to a future device; {@code false} otherwise.
      * @param which Flags indicating which wallpaper(s) to configure with the new imagery.
      *
-     * @see #FLAG_SET_LOCK_WALLPAPER
-     * @see #FLAG_SET_SYSTEM_WALLPAPER
+     * @see #FLAG_SET_LOCK
+     * @see #FLAG_SET_SYSTEM
      *
      * @throws IOException
      */
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index a34e8551e..dd70b5d 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -268,7 +268,7 @@
             "android.app.action.BUGREPORT_SHARE";
 
     /**
-     * Broadcast action: notify that a new batch of device logs is ready to be collected.
+     * Broadcast action: notify that a new batch of security logs is ready to be collected.
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -284,10 +284,11 @@
     public static final String EXTRA_BUGREPORT_HASH = "android.app.extra.BUGREPORT_HASH";
 
     /**
-     * An {@code int} failure code representing the reason of the bugreport failure.
+     * An {@code int} failure code representing the reason of the bugreport failure. One of
+     * {@link #BUGREPORT_FAILURE_FAILED_COMPLETING}
+     * or {@link #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE}
      *
      * @see #ACTION_BUGREPORT_FAILED
-     * @see #BUGREPORT_FAILURE_FAILED_COMPLETING, #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE
      * @hide
      */
     public static final String EXTRA_BUGREPORT_FAILURE_REASON =
@@ -305,9 +306,24 @@
         BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE
     })
     public @interface BugreportFailureCode {}
-    /** Bugreport completion process failed. */
+
+    /**
+     * Bugreport completion process failed.
+     *
+     * <p>If this error code is received, the requesting of bugreport can be retried.
+     * @see DevicePolicyManager#requestBugreport
+     */
     public static final int BUGREPORT_FAILURE_FAILED_COMPLETING = 0;
-    /** Bugreport is no longer available for collection. */
+
+    /**
+     * Bugreport has been created, but is no longer available for collection.
+     *
+     * <p>This error likely occurs because the user of the device hasn't consented to share
+     * the bugreport for a long period after its creation.
+     *
+     * <p>If this error code is received, the requesting of bugreport can be retried.
+     * @see DevicePolicyManager#requestBugreport
+     */
     public static final int BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE = 1;
 
     /** @hide */
@@ -598,7 +614,8 @@
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
      * @param failureCode int containing failure code. One of
-     * #BUGREPORT_FAILURE_FAILED_COMPLETING or #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE
+     * {@link #BUGREPORT_FAILURE_FAILED_COMPLETING}
+     * or {@link #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE}
      * @see DevicePolicyManager#requestBugreport
      */
     public void onBugreportFailed(Context context, Intent intent,
@@ -606,13 +623,13 @@
     }
 
     /**
-     * Called when a new batch of device logs can be retrieved.
+     * Called when a new batch of security logs can be retrieved.
      *
      * <p>This callback is only applicable to device owners.
      *
      * @param context The running context as per {@link #onReceive}.
      * @param intent The received intent as per {@link #onReceive}.
-     * @see DevicePolicyManager#retrieveDeviceLogs(ComponentName)
+     * @see DevicePolicyManager#retrieveSecurityLogs(ComponentName)
      */
     public void onSecurityLogsAvailable(Context context, Intent intent) {
     }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index af9705f..b7d9b80 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -25,16 +25,13 @@
 import android.annotation.SystemApi;
 import android.annotation.UserIdInt;
 import android.app.Activity;
-import android.auditing.SecurityLog;
-import android.auditing.SecurityLog.SecurityEvent;
+import android.app.admin.SecurityLog.SecurityEvent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
-import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.graphics.Bitmap;
 import android.net.ProxyInfo;
@@ -51,13 +48,12 @@
 import android.provider.Settings;
 import android.security.Credentials;
 import android.service.restrictions.RestrictionsReceiver;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.org.conscrypt.TrustedCertificateStore;
 
-import org.xmlpull.v1.XmlPullParserException;
-
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.lang.annotation.Retention;
@@ -80,18 +76,18 @@
 
 /**
  * Public interface for managing policies enforced on a device. Most clients of this class must be
- * registered with the system as a
- * <a href="{@docRoot}guide/topics/admin/device-admin.html">device administrator</a>. Additionally,
- * a device administrator may be registered as either a profile or device owner. A given method is
- * accessible to all device administrators unless the documentation for that method specifies that
- * it is restricted to either device or profile owners.
- *
+ * registered with the system as a <a href="{@docRoot}guide/topics/admin/device-admin.html">device
+ * administrator</a>. Additionally, a device administrator may be registered as either a profile or
+ * device owner. A given method is accessible to all device administrators unless the documentation
+ * for that method specifies that it is restricted to either device or profile owners. Any
+ * application calling an api may only pass as an argument a device administrator component it
+ * owns. Otherwise, a {@link SecurityException} will be thrown.
  * <div class="special reference">
  * <h3>Developer Guides</h3>
- * <p>For more information about managing policies for device administration, read the
- * <a href="{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a>
- * developer guide.
- * </div>
+ * <p>
+ * For more information about managing policies for device administration, read the <a href=
+ * "{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a> developer
+ * guide. </div>
  */
 public class DevicePolicyManager {
     private static String TAG = "DevicePolicyManager";
@@ -1032,8 +1028,11 @@
     public @interface UserProvisioningState {}
 
     /**
-     * Return true if the given administrator component is currently
-     * active (enabled) in the system.
+     * Return true if the given administrator component is currently active (enabled) in the system.
+     *
+     * @param admin The administrator component to check for.
+     * @return {@code true} if {@code admin} is currently enabled in the system, {@code false}
+     *         otherwise
      */
     public boolean isAdminActive(@NonNull ComponentName admin) {
         return isAdminActiveAsUser(admin, myUserId());
@@ -1127,6 +1126,9 @@
      *
      * <p>Note that the operation is not synchronous and the admin might still be active (as
      * indicated by {@link #getActiveAdmins()}) by the time this method returns.
+     *
+     * @param admin The administration compononent to remove.
+     * @throws SecurityException if the caller is not in the owner application of {@code admin}.
      */
     public void removeActiveAdmin(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -1139,13 +1141,14 @@
     }
 
     /**
-     * Returns true if an administrator has been granted a particular device policy.  This can
-     * be used to check whether the administrator was activated under an earlier set of policies,
-     * but requires additional policies after an upgrade.
+     * Returns true if an administrator has been granted a particular device policy. This can be
+     * used to check whether the administrator was activated under an earlier set of policies, but
+     * requires additional policies after an upgrade.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.  Must be
-     * an active administrator, or an exception will be thrown.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Must be an
+     *            active administrator, or an exception will be thrown.
      * @param usesPolicy Which uses-policy to check, as defined in {@link DeviceAdminInfo}.
+     * @throws SecurityException if {@code admin} is not an active administrator.
      */
     public boolean hasGrantedPolicy(@NonNull ComponentName admin, int usesPolicy) {
         if (mService != null) {
@@ -1252,34 +1255,32 @@
     public static final int PASSWORD_QUALITY_MANAGED = 0x80000;
 
     /**
-     * Called by an application that is administering the device to set the
-     * password restrictions it is imposing.  After setting this, the user
-     * will not be able to enter a new password that is not at least as
-     * restrictive as what has been set.  Note that the current password
-     * will remain until the user has set a new one, so the change does not
-     * take place immediately.  To prompt the user for a new password, use
-     * {@link #ACTION_SET_NEW_PASSWORD} or
+     * Called by an application that is administering the device to set the password restrictions it
+     * is imposing. After setting this, the user will not be able to enter a new password that is
+     * not at least as restrictive as what has been set. Note that the current password will remain
+     * until the user has set a new one, so the change does not take place immediately. To prompt
+     * the user for a new password, use {@link #ACTION_SET_NEW_PASSWORD} or
      * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after calling this method.
-     *
-     * <p>Quality constants are ordered so that higher values are more restrictive;
-     * thus the highest requested quality constant (between the policy set here,
-     * the user's preference, and any other considerations) is the one that
-     * is in effect.
-     *
-     * <p>The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
-     * this method; if it has not, a security exception will be thrown.
-     *
-     * <p>This method can be called on the {@link DevicePolicyManager} instance
-     * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
-     * restrictions on the parent profile.
+     * <p>
+     * Quality constants are ordered so that higher values are more restrictive; thus the highest
+     * requested quality constant (between the policy set here, the user's preference, and any other
+     * considerations) is the one that is in effect.
+     * <p>
+     * The calling device admin must have requested
+     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
+     * not, a security exception will be thrown.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
+     * profile.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @param quality The new desired quality.  One of
-     * {@link #PASSWORD_QUALITY_UNSPECIFIED}, {@link #PASSWORD_QUALITY_SOMETHING},
-     * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX},
-     * {@link #PASSWORD_QUALITY_ALPHABETIC}, {@link #PASSWORD_QUALITY_ALPHANUMERIC}
-     * or {@link #PASSWORD_QUALITY_COMPLEX}.
+     * @param quality The new desired quality. One of {@link #PASSWORD_QUALITY_UNSPECIFIED},
+     *            {@link #PASSWORD_QUALITY_SOMETHING}, {@link #PASSWORD_QUALITY_NUMERIC},
+     *            {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX}, {@link #PASSWORD_QUALITY_ALPHABETIC},
+     *            {@link #PASSWORD_QUALITY_ALPHANUMERIC} or {@link #PASSWORD_QUALITY_COMPLEX}.
+     * @throws SecurityException if {@code admin} is not an active administrator or if {@code admin}
+     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
      */
     public void setPasswordQuality(@NonNull ComponentName admin, int quality) {
         if (mService != null) {
@@ -1320,30 +1321,30 @@
     }
 
     /**
-     * Called by an application that is administering the device to set the
-     * minimum allowed password length.  After setting this, the user
-     * will not be able to enter a new password that is not at least as
-     * restrictive as what has been set.  Note that the current password
-     * will remain until the user has set a new one, so the change does not
-     * take place immediately.  To prompt the user for a new password, use
-     * {@link #ACTION_SET_NEW_PASSWORD}  or
-     * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value.  This
-     * constraint is only imposed if the administrator has also requested either
-     * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX},
-     * {@link #PASSWORD_QUALITY_ALPHABETIC}, {@link #PASSWORD_QUALITY_ALPHANUMERIC},
-     * or {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}.
-     *
-     * <p>The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
-     * this method; if it has not, a security exception will be thrown.
-     *
-     * <p>This method can be called on the {@link DevicePolicyManager} instance
-     * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
-     * restrictions on the parent profile.
+     * Called by an application that is administering the device to set the minimum allowed password
+     * length. After setting this, the user will not be able to enter a new password that is not at
+     * least as restrictive as what has been set. Note that the current password will remain until
+     * the user has set a new one, so the change does not take place immediately. To prompt the user
+     * for a new password, use {@link #ACTION_SET_NEW_PASSWORD} or
+     * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This constraint is
+     * only imposed if the administrator has also requested either {@link #PASSWORD_QUALITY_NUMERIC}
+     * , {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX}, {@link #PASSWORD_QUALITY_ALPHABETIC},
+     * {@link #PASSWORD_QUALITY_ALPHANUMERIC}, or {@link #PASSWORD_QUALITY_COMPLEX} with
+     * {@link #setPasswordQuality}.
+     * <p>
+     * The calling device admin must have requested
+     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
+     * not, a security exception will be thrown.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
+     * profile.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @param length The new desired minimum password length.  A value of 0
-     * means there is no restriction.
+     * @param length The new desired minimum password length. A value of 0 means there is no
+     *            restriction.
+     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
+     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
      */
     public void setPasswordMinimumLength(@NonNull ComponentName admin, int length) {
         if (mService != null) {
@@ -1385,31 +1386,28 @@
     }
 
     /**
-     * Called by an application that is administering the device to set the
-     * minimum number of upper case letters required in the password. After
-     * setting this, the user will not be able to enter a new password that is
-     * not at least as restrictive as what has been set. Note that the current
-     * password will remain until the user has set a new one, so the change does
-     * not take place immediately. To prompt the user for a new password, use
-     * {@link #ACTION_SET_NEW_PASSWORD}  or
-     * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This
-     * constraint is only imposed if the administrator has also requested
-     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The
-     * default value is 0.
+     * Called by an application that is administering the device to set the minimum number of upper
+     * case letters required in the password. After setting this, the user will not be able to enter
+     * a new password that is not at least as restrictive as what has been set. Note that the
+     * current password will remain until the user has set a new one, so the change does not take
+     * place immediately. To prompt the user for a new password, use
+     * {@link #ACTION_SET_NEW_PASSWORD} or {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after
+     * setting this value. This constraint is only imposed if the administrator has also requested
+     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The default value is 0.
      * <p>
      * The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
-     * this method; if it has not, a security exception will be thrown.
+     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
+     * not, a security exception will be thrown.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
+     * profile.
      *
-     * <p>This method can be called on the {@link DevicePolicyManager} instance
-     * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
-     * restrictions on the parent profile.
-     *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated
-     *            with.
-     * @param length The new desired minimum number of upper case letters
-     *            required in the password. A value of 0 means there is no
-     *            restriction.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param length The new desired minimum number of upper case letters required in the password.
+     *            A value of 0 means there is no restriction.
+     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
+     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
      */
     public void setPasswordMinimumUpperCase(@NonNull ComponentName admin, int length) {
         if (mService != null) {
@@ -1457,31 +1455,28 @@
     }
 
     /**
-     * Called by an application that is administering the device to set the
-     * minimum number of lower case letters required in the password. After
-     * setting this, the user will not be able to enter a new password that is
-     * not at least as restrictive as what has been set. Note that the current
-     * password will remain until the user has set a new one, so the change does
-     * not take place immediately. To prompt the user for a new password, use
-     * {@link #ACTION_SET_NEW_PASSWORD} or
-     * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This
-     * constraint is only imposed if the administrator has also requested
-     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The
-     * default value is 0.
+     * Called by an application that is administering the device to set the minimum number of lower
+     * case letters required in the password. After setting this, the user will not be able to enter
+     * a new password that is not at least as restrictive as what has been set. Note that the
+     * current password will remain until the user has set a new one, so the change does not take
+     * place immediately. To prompt the user for a new password, use
+     * {@link #ACTION_SET_NEW_PASSWORD} or {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after
+     * setting this value. This constraint is only imposed if the administrator has also requested
+     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The default value is 0.
      * <p>
      * The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
-     * this method; if it has not, a security exception will be thrown.
+     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
+     * not, a security exception will be thrown.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
+     * profile.
      *
-     * <p>This method can be called on the {@link DevicePolicyManager} instance
-     * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
-     * restrictions on the parent profile.
-     *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated
-     *            with.
-     * @param length The new desired minimum number of lower case letters
-     *            required in the password. A value of 0 means there is no
-     *            restriction.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param length The new desired minimum number of lower case letters required in the password.
+     *            A value of 0 means there is no restriction.
+     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
+     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
      */
     public void setPasswordMinimumLowerCase(@NonNull ComponentName admin, int length) {
         if (mService != null) {
@@ -1529,30 +1524,28 @@
     }
 
     /**
-     * Called by an application that is administering the device to set the
-     * minimum number of letters required in the password. After setting this,
-     * the user will not be able to enter a new password that is not at least as
-     * restrictive as what has been set. Note that the current password will
-     * remain until the user has set a new one, so the change does not take
-     * place immediately. To prompt the user for a new password, use
-     * {@link #ACTION_SET_NEW_PASSWORD} or
-     * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This
-     * constraint is only imposed if the administrator has also requested
-     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The
-     * default value is 1.
+     * Called by an application that is administering the device to set the minimum number of
+     * letters required in the password. After setting this, the user will not be able to enter a
+     * new password that is not at least as restrictive as what has been set. Note that the current
+     * password will remain until the user has set a new one, so the change does not take place
+     * immediately. To prompt the user for a new password, use {@link #ACTION_SET_NEW_PASSWORD} or
+     * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This constraint is
+     * only imposed if the administrator has also requested {@link #PASSWORD_QUALITY_COMPLEX} with
+     * {@link #setPasswordQuality}. The default value is 1.
      * <p>
      * The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
-     * this method; if it has not, a security exception will be thrown.
+     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
+     * not, a security exception will be thrown.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
+     * profile.
      *
-     * <p>This method can be called on the {@link DevicePolicyManager} instance
-     * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
-     * restrictions on the parent profile.
-     *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated
-     *            with.
-     * @param length The new desired minimum number of letters required in the
-     *            password. A value of 0 means there is no restriction.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param length The new desired minimum number of letters required in the password. A value of
+     *            0 means there is no restriction.
+     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
+     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
      */
     public void setPasswordMinimumLetters(@NonNull ComponentName admin, int length) {
         if (mService != null) {
@@ -1599,30 +1592,28 @@
     }
 
     /**
-     * Called by an application that is administering the device to set the
-     * minimum number of numerical digits required in the password. After
-     * setting this, the user will not be able to enter a new password that is
-     * not at least as restrictive as what has been set. Note that the current
-     * password will remain until the user has set a new one, so the change does
-     * not take place immediately. To prompt the user for a new password, use
-     * {@link #ACTION_SET_NEW_PASSWORD} or
-     * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This
-     * constraint is only imposed if the administrator has also requested
-     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The
-     * default value is 1.
+     * Called by an application that is administering the device to set the minimum number of
+     * numerical digits required in the password. After setting this, the user will not be able to
+     * enter a new password that is not at least as restrictive as what has been set. Note that the
+     * current password will remain until the user has set a new one, so the change does not take
+     * place immediately. To prompt the user for a new password, use
+     * {@link #ACTION_SET_NEW_PASSWORD} or {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after
+     * setting this value. This constraint is only imposed if the administrator has also requested
+     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The default value is 1.
      * <p>
      * The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
-     * this method; if it has not, a security exception will be thrown.
+     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
+     * not, a security exception will be thrown.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
+     * profile.
      *
-     * <p>This method can be called on the {@link DevicePolicyManager} instance
-     * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
-     * restrictions on the parent profile.
-     *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated
-     *            with.
-     * @param length The new desired minimum number of numerical digits required
-     *            in the password. A value of 0 means there is no restriction.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param length The new desired minimum number of numerical digits required in the password. A
+     *            value of 0 means there is no restriction.
+     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
+     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
      */
     public void setPasswordMinimumNumeric(@NonNull ComponentName admin, int length) {
         if (mService != null) {
@@ -1669,30 +1660,28 @@
     }
 
     /**
-     * Called by an application that is administering the device to set the
-     * minimum number of symbols required in the password. After setting this,
-     * the user will not be able to enter a new password that is not at least as
-     * restrictive as what has been set. Note that the current password will
-     * remain until the user has set a new one, so the change does not take
-     * place immediately. To prompt the user for a new password, use
-     * {@link #ACTION_SET_NEW_PASSWORD} or
-     * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This
-     * constraint is only imposed if the administrator has also requested
-     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The
-     * default value is 1.
+     * Called by an application that is administering the device to set the minimum number of
+     * symbols required in the password. After setting this, the user will not be able to enter a
+     * new password that is not at least as restrictive as what has been set. Note that the current
+     * password will remain until the user has set a new one, so the change does not take place
+     * immediately. To prompt the user for a new password, use {@link #ACTION_SET_NEW_PASSWORD} or
+     * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This constraint is
+     * only imposed if the administrator has also requested {@link #PASSWORD_QUALITY_COMPLEX} with
+     * {@link #setPasswordQuality}. The default value is 1.
      * <p>
      * The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
-     * this method; if it has not, a security exception will be thrown.
+     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
+     * not, a security exception will be thrown.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
+     * profile.
      *
-     * <p>This method can be called on the {@link DevicePolicyManager} instance
-     * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
-     * restrictions on the parent profile.
-     *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated
-     *            with.
-     * @param length The new desired minimum number of symbols required in the
-     *            password. A value of 0 means there is no restriction.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param length The new desired minimum number of symbols required in the password. A value of
+     *            0 means there is no restriction.
+     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
+     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
      */
     public void setPasswordMinimumSymbols(@NonNull ComponentName admin, int length) {
         if (mService != null) {
@@ -1738,30 +1727,28 @@
     }
 
     /**
-     * Called by an application that is administering the device to set the
-     * minimum number of non-letter characters (numerical digits or symbols)
-     * required in the password. After setting this, the user will not be able
-     * to enter a new password that is not at least as restrictive as what has
-     * been set. Note that the current password will remain until the user has
-     * set a new one, so the change does not take place immediately. To prompt
-     * the user for a new password, use {@link #ACTION_SET_NEW_PASSWORD} or
-     * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after
-     * setting this value. This constraint is only imposed if the administrator
-     * has also requested {@link #PASSWORD_QUALITY_COMPLEX} with
-     * {@link #setPasswordQuality}. The default value is 0.
+     * Called by an application that is administering the device to set the minimum number of
+     * non-letter characters (numerical digits or symbols) required in the password. After setting
+     * this, the user will not be able to enter a new password that is not at least as restrictive
+     * as what has been set. Note that the current password will remain until the user has set a new
+     * one, so the change does not take place immediately. To prompt the user for a new password,
+     * use {@link #ACTION_SET_NEW_PASSWORD} or {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after
+     * setting this value. This constraint is only imposed if the administrator has also requested
+     * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The default value is 0.
      * <p>
      * The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
-     * this method; if it has not, a security exception will be thrown.
+     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
+     * not, a security exception will be thrown.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
+     * profile.
      *
-     * <p>This method can be called on the {@link DevicePolicyManager} instance
-     * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
-     * restrictions on the parent profile.
-     *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated
-     *            with.
-     * @param length The new desired minimum number of letters required in the
-     *            password. A value of 0 means there is no restriction.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param length The new desired minimum number of letters required in the password. A value of
+     *            0 means there is no restriction.
+     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
+     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
      */
     public void setPasswordMinimumNonLetter(@NonNull ComponentName admin, int length) {
         if (mService != null) {
@@ -1807,33 +1794,31 @@
         return 0;
     }
 
-  /**
-   * Called by an application that is administering the device to set the length
-   * of the password history. After setting this, the user will not be able to
-   * enter a new password that is the same as any password in the history. Note
-   * that the current password will remain until the user has set a new one, so
-   * the change does not take place immediately. To prompt the user for a new
-   * password, use {@link #ACTION_SET_NEW_PASSWORD} or
-   * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value.
-   * This constraint is only imposed if the administrator has also requested
-   * either {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX}
-   * {@link #PASSWORD_QUALITY_ALPHABETIC}, or {@link #PASSWORD_QUALITY_ALPHANUMERIC}
-   * with {@link #setPasswordQuality}.
-   *
-   * <p>
-   * The calling device admin must have requested
-   * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this
-   * method; if it has not, a security exception will be thrown.
-   *
-   * <p>This method can be called on the {@link DevicePolicyManager} instance
-   * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
-   * restrictions on the parent profile.
-   *
-   * @param admin Which {@link DeviceAdminReceiver} this request is associated
-   *        with.
-   * @param length The new desired length of password history. A value of 0
-   *        means there is no restriction.
-   */
+    /**
+     * Called by an application that is administering the device to set the length of the password
+     * history. After setting this, the user will not be able to enter a new password that is the
+     * same as any password in the history. Note that the current password will remain until the
+     * user has set a new one, so the change does not take place immediately. To prompt the user for
+     * a new password, use {@link #ACTION_SET_NEW_PASSWORD} or
+     * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This constraint is
+     * only imposed if the administrator has also requested either {@link #PASSWORD_QUALITY_NUMERIC}
+     * , {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX} {@link #PASSWORD_QUALITY_ALPHABETIC}, or
+     * {@link #PASSWORD_QUALITY_ALPHANUMERIC} with {@link #setPasswordQuality}.
+     * <p>
+     * The calling device admin must have requested
+     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
+     * not, a security exception will be thrown.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
+     * profile.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param length The new desired length of password history. A value of 0 means there is no
+     *            restriction.
+     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
+     *             does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
+     */
     public void setPasswordHistoryLength(@NonNull ComponentName admin, int length) {
         if (mService != null) {
             try {
@@ -1845,30 +1830,32 @@
     }
 
     /**
-     * Called by a device admin to set the password expiration timeout. Calling this method
-     * will restart the countdown for password expiration for the given admin, as will changing
-     * the device password (for all admins).
-     *
-     * <p>The provided timeout is the time delta in ms and will be added to the current time.
-     * For example, to have the password expire 5 days from now, timeout would be
-     * 5 * 86400 * 1000 = 432000000 ms for timeout.
-     *
-     * <p>To disable password expiration, a value of 0 may be used for timeout.
-     *
-     * <p>The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to be able to call this
-     * method; if it has not, a security exception will be thrown.
-     *
-     * <p> Note that setting the password will automatically reset the expiration time for all
-     * active admins. Active admins do not need to explicitly call this method in that case.
-     *
-     * <p>This method can be called on the {@link DevicePolicyManager} instance
-     * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
-     * restrictions on the parent profile.
+     * Called by a device admin to set the password expiration timeout. Calling this method will
+     * restart the countdown for password expiration for the given admin, as will changing the
+     * device password (for all admins).
+     * <p>
+     * The provided timeout is the time delta in ms and will be added to the current time. For
+     * example, to have the password expire 5 days from now, timeout would be 5 * 86400 * 1000 =
+     * 432000000 ms for timeout.
+     * <p>
+     * To disable password expiration, a value of 0 may be used for timeout.
+     * <p>
+     * The calling device admin must have requested
+     * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to be able to call this method; if it has
+     * not, a security exception will be thrown.
+     * <p>
+     * Note that setting the password will automatically reset the expiration time for all active
+     * admins. Active admins do not need to explicitly call this method in that case.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
+     * profile.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @param timeout The limit (in ms) that a password can remain in effect. A value of 0
-     *        means there is no restriction (unlimited).
+     * @param timeout The limit (in ms) that a password can remain in effect. A value of 0 means
+     *            there is no restriction (unlimited).
+     * @throws SecurityException if {@code admin} is not an active administrator or {@code admin}
+     *             does not use {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD}
      */
     public void setPasswordExpirationTimeout(@NonNull ComponentName admin, long timeout) {
         if (mService != null) {
@@ -1970,20 +1957,22 @@
     }
 
     /**
-     * Determine whether the current password the user has set is sufficient
-     * to meet the policy requirements (e.g. quality, minimum length) that have been
-     * requested by the admins of this user and its participating profiles.
-     * Restrictions on profiles that have a separate challenge are not taken into account.
-     *
-     * <p>The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
-     * this method; if it has not, a security exception will be thrown.
-     *
-     * <p>This method can be called on the {@link DevicePolicyManager} instance
-     * returned by {@link #getParentProfileInstance(ComponentName)} in order to determine
-     * if the password set on the parent profile is sufficient.
+     * Determine whether the current password the user has set is sufficient to meet the policy
+     * requirements (e.g. quality, minimum length) that have been requested by the admins of this
+     * user and its participating profiles. Restrictions on profiles that have a separate challenge
+     * are not taken into account.
+     * <p>
+     * The calling device admin must have requested
+     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has
+     * not, a security exception will be thrown.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to determine if the password set on
+     * the parent profile is sufficient.
      *
      * @return Returns true if the password meets the current requirements, else false.
+     * @throws SecurityException if the calling application does not own an active administrator
+     *             that uses {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
      */
     public boolean isActivePasswordSufficient() {
         if (mService != null) {
@@ -2003,6 +1992,7 @@
      *
      * @param userHandle the userId of the profile to check the password for.
      * @return Returns true if the password would meet the current requirements, else false.
+     * @throws SecurityException if {@code userHandle} is not a managed profile.
      * @hide
      */
     public boolean isProfileActivePasswordSufficientForParent(int userHandle) {
@@ -2017,16 +2007,20 @@
     }
 
     /**
-     * Retrieve the number of times the user has failed at entering a
-     * password since that last successful password entry.
+     * Retrieve the number of times the user has failed at entering a password since that last
+     * successful password entry.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to retrieve the number of failed
+     * password attemts for the parent user.
+     * <p>
+     * The calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN}
+     * to be able to call this method; if it has not, a security exception will be thrown.
      *
-     * <p>This method can be called on the {@link DevicePolicyManager} instance
-     * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve
-     * the number of failed password attemts for the parent user.
-     *
-     * <p>The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to be able to call
-     * this method; if it has not, a security exception will be thrown.
+     * @return The number of times user has entered an incorrect password since the last correct
+     *         password entry.
+     * @throws SecurityException if the calling application does not own an active administrator
+     *             that uses {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN}
      */
     public int getCurrentFailedPasswordAttempts() {
         return getCurrentFailedPasswordAttempts(myUserId());
@@ -2071,27 +2065,28 @@
     }
 
     /**
-     * Setting this to a value greater than zero enables a built-in policy
-     * that will perform a device or profile wipe after too many incorrect
-     * device-unlock passwords have been entered.  This built-in policy combines
-     * watching for failed passwords and wiping the device, and requires
-     * that you request both {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} and
+     * Setting this to a value greater than zero enables a built-in policy that will perform a
+     * device or profile wipe after too many incorrect device-unlock passwords have been entered.
+     * This built-in policy combines watching for failed passwords and wiping the device, and
+     * requires that you request both {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} and
      * {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA}}.
-     *
-     * <p>To implement any other policy (e.g. wiping data for a particular
-     * application only, erasing or revoking credentials, or reporting the
-     * failure to a server), you should implement
-     * {@link DeviceAdminReceiver#onPasswordFailed(Context, android.content.Intent)}
-     * instead.  Do not use this API, because if the maximum count is reached,
-     * the device or profile will be wiped immediately, and your callback will not be invoked.
-     *
-     * <p>This method can be called on the {@link DevicePolicyManager} instance
-     * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
-     * a value on the parent profile.
+     * <p>
+     * To implement any other policy (e.g. wiping data for a particular application only, erasing or
+     * revoking credentials, or reporting the failure to a server), you should implement
+     * {@link DeviceAdminReceiver#onPasswordFailed(Context, android.content.Intent)} instead. Do not
+     * use this API, because if the maximum count is reached, the device or profile will be wiped
+     * immediately, and your callback will not be invoked.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to set a value on the parent
+     * profile.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @param num The number of failed password attempts at which point the
-     * device or profile will be wiped.
+     * @param num The number of failed password attempts at which point the device or profile will
+     *            be wiped.
+     * @throws SecurityException if {@code admin} is not an active administrator or does not use
+     *             both {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} and
+     *             {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA}.
      */
     public void setMaximumFailedPasswordsForWipe(@NonNull ComponentName admin, int num) {
         if (mService != null) {
@@ -2169,42 +2164,41 @@
     public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 0x0002;
 
     /**
-     * Force a new device unlock password (the password needed to access the
-     * entire device, not for individual accounts) on the user.  This takes
-     * effect immediately.
-     *
-     * <p>Calling this from a managed profile that shares the password with the owner profile
-     * will throw a security exception.
-     *
-     * <p><em>Note: This API has been limited as of {@link android.os.Build.VERSION_CODES#N} for
+     * Force a new device unlock password (the password needed to access the entire device, not for
+     * individual accounts) on the user. This takes effect immediately.
+     * <p>
+     * Calling this from a managed profile that shares the password with the owner profile will
+     * throw a security exception.
+     * <p>
+     * <em>Note: This API has been limited as of {@link android.os.Build.VERSION_CODES#N} for
      * device admins that are not device owner and not profile owner.
      * The password can now only be changed if there is currently no password set.  Device owner
      * and profile owner can still do this.</em>
-     *
-     * <p>The given password must be sufficient for the
-     * current password quality and length constraints as returned by
-     * {@link #getPasswordQuality(ComponentName)} and
-     * {@link #getPasswordMinimumLength(ComponentName)}; if it does not meet
-     * these constraints, then it will be rejected and false returned.  Note
-     * that the password may be a stronger quality (containing alphanumeric
-     * characters when the requested quality is only numeric), in which case
-     * the currently active quality will be increased to match.
-     *
-     * <p>Calling with a null or empty password will clear any existing PIN,
-     * pattern or password if the current password constraints allow it. <em>Note: This will not
+     * <p>
+     * The given password must be sufficient for the current password quality and length constraints
+     * as returned by {@link #getPasswordQuality(ComponentName)} and
+     * {@link #getPasswordMinimumLength(ComponentName)}; if it does not meet these constraints, then
+     * it will be rejected and false returned. Note that the password may be a stronger quality
+     * (containing alphanumeric characters when the requested quality is only numeric), in which
+     * case the currently active quality will be increased to match.
+     * <p>
+     * Calling with a null or empty password will clear any existing PIN, pattern or password if the
+     * current password constraints allow it. <em>Note: This will not
      * work in {@link android.os.Build.VERSION_CODES#N} and later for device admins that are not
      * device owner and not profile owner.  Once set, the password cannot be changed to null or
      * empty, except by device owner or profile owner.</em>
-     *
-     * <p>The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call
-     * this method; if it has not, a security exception will be thrown.
+     * <p>
+     * The calling device admin must have requested
+     * {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call this method; if it has
+     * not, a security exception will be thrown.
      *
      * @param password The new password for the user. Null or empty clears the password.
      * @param flags May be 0 or combination of {@link #RESET_PASSWORD_REQUIRE_ENTRY} and
-     *              {@link #RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT}.
-     * @return Returns true if the password was applied, or false if it is
-     * not acceptable for the current constraints or if the user has not been decrypted yet.
+     *            {@link #RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT}.
+     * @return Returns true if the password was applied, or false if it is not acceptable for the
+     *         current constraints or if the user has not been decrypted yet.
+     * @throws SecurityException if the calling application does not own an active administrator
+     *             that uses {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD}
      */
     public boolean resetPassword(String password, int flags) {
         if (mParentInstance) {
@@ -2221,21 +2215,22 @@
     }
 
     /**
-     * Called by an application that is administering the device to set the
-     * maximum time for user activity until the device will lock.  This limits
-     * the length that the user can set.  It takes effect immediately.
-     *
-     * <p>The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} to be able to call
-     * this method; if it has not, a security exception will be thrown.
-     *
-     * <p>This method can be called on the {@link DevicePolicyManager} instance
-     * returned by {@link #getParentProfileInstance(ComponentName)} in order to set
-     * restrictions on the parent profile.
+     * Called by an application that is administering the device to set the maximum time for user
+     * activity until the device will lock. This limits the length that the user can set. It takes
+     * effect immediately.
+     * <p>
+     * The calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK}
+     * to be able to call this method; if it has not, a security exception will be thrown.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
+     * profile.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @param timeMs The new desired maximum time to lock in milliseconds.
-     * A value of 0 means there is no restriction.
+     * @param timeMs The new desired maximum time to lock in milliseconds. A value of 0 means there
+     *            is no restriction.
+     * @throws SecurityException if {@code admin} is not an active administrator or it does not use
+     *             {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK}
      */
     public void setMaximumTimeToLock(@NonNull ComponentName admin, long timeMs) {
         if (mService != null) {
@@ -2278,16 +2273,17 @@
     }
 
     /**
-     * Make the device lock immediately, as if the lock screen timeout has
-     * expired at the point of this call.
+     * Make the device lock immediately, as if the lock screen timeout has expired at the point of
+     * this call.
+     * <p>
+     * The calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK}
+     * to be able to call this method; if it has not, a security exception will be thrown.
+     * <p>
+     * This method can be called on the {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} in order to lock the parent profile.
      *
-     * <p>The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} to be able to call
-     * this method; if it has not, a security exception will be thrown.
-     *
-     * <p>This method can be called on the {@link DevicePolicyManager} instance
-     * returned by {@link #getParentProfileInstance(ComponentName)} in order to lock
-     * the parent profile.
+     * @throws SecurityException if the calling application does not own an active administrator
+     *             that uses {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK}
      */
     public void lockNow() {
         if (mService != null) {
@@ -2315,16 +2311,16 @@
     public static final int WIPE_RESET_PROTECTION_DATA = 0x0002;
 
     /**
-     * Ask the user data be wiped.  Wiping the primary user will cause the
-     * device to reboot, erasing all user data while next booting up.
+     * Ask the user data be wiped. Wiping the primary user will cause the device to reboot, erasing
+     * all user data while next booting up.
+     * <p>
+     * The calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} to
+     * be able to call this method; if it has not, a security exception will be thrown.
      *
-     * <p>The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} to be able to call
-     * this method; if it has not, a security exception will be thrown.
-     *
-     * @param flags Bit mask of additional options: currently supported flags
-     * are {@link #WIPE_EXTERNAL_STORAGE} and
-     * {@link #WIPE_RESET_PROTECTION_DATA}.
+     * @param flags Bit mask of additional options: currently supported flags are
+     *            {@link #WIPE_EXTERNAL_STORAGE} and {@link #WIPE_RESET_PROTECTION_DATA}.
+     * @throws SecurityException if the calling application does not own an active administrator
+     *             that uses {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA}
      */
     public void wipeData(int flags) {
         if (mService != null) {
@@ -2408,20 +2404,20 @@
     }
 
     /**
-     * Set a network-independent global HTTP proxy.  This is not normally what you want
-     * for typical HTTP proxies - they are generally network dependent.  However if you're
-     * doing something unusual like general internal filtering this may be useful.  On
-     * a private network where the proxy is not accessible, you may break HTTP using this.
+     * Set a network-independent global HTTP proxy. This is not normally what you want for typical
+     * HTTP proxies - they are generally network dependent. However if you're doing something
+     * unusual like general internal filtering this may be useful. On a private network where the
+     * proxy is not accessible, you may break HTTP using this.
+     * <p>
+     * This method requires the caller to be the device owner.
+     * <p>
+     * This proxy is only a recommendation and it is possible that some apps will ignore it.
      *
-     * <p>This method requires the caller to be the device owner.
-     *
-     * <p>This proxy is only a recommendation and it is possible that some apps will ignore it.
      * @see ProxyInfo
-     *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated
-     *            with.
-     * @param proxyInfo The a {@link ProxyInfo} object defining the new global
-     *        HTTP proxy.  A {@code null} value will clear the global HTTP proxy.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param proxyInfo The a {@link ProxyInfo} object defining the new global HTTP proxy. A
+     *            {@code null} value will clear the global HTTP proxy.
+     * @throws SecurityException if {@code admin} is not the device owner.
      */
     public void setRecommendedGlobalProxy(@NonNull ComponentName admin, @Nullable ProxyInfo
             proxyInfo) {
@@ -2487,6 +2483,12 @@
     public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4;
 
     /**
+     * Result code for {@link #getStorageEncryptionStatus}:
+     * indicating that encryption is active and the encryption key is tied to the user.
+     */
+    public static final int ENCRYPTION_STATUS_ACTIVE_PER_USER = 5;
+
+    /**
      * Activity action: begin the process of encrypting data on the device.  This activity should
      * be launched after using {@link #setStorageEncryption} to request encryption be activated.
      * After resuming from this activity, use {@link #getStorageEncryption}
@@ -2538,36 +2540,35 @@
     public static final int KEYGUARD_DISABLE_FEATURES_ALL = 0x7fffffff;
 
     /**
-     * Called by an application that is administering the device to
-     * request that the storage system be encrypted.
-     *
-     * <p>When multiple device administrators attempt to control device
-     * encryption, the most secure, supported setting will always be
-     * used.  If any device administrator requests device encryption,
-     * it will be enabled;  Conversely, if a device administrator
-     * attempts to disable device encryption while another
-     * device administrator has enabled it, the call to disable will
+     * Called by an application that is administering the device to request that the storage system
+     * be encrypted.
+     * <p>
+     * When multiple device administrators attempt to control device encryption, the most secure,
+     * supported setting will always be used. If any device administrator requests device
+     * encryption, it will be enabled; Conversely, if a device administrator attempts to disable
+     * device encryption while another device administrator has enabled it, the call to disable will
      * fail (most commonly returning {@link #ENCRYPTION_STATUS_ACTIVE}).
-     *
-     * <p>This policy controls encryption of the secure (application data) storage area.  Data
-     * written to other storage areas may or may not be encrypted, and this policy does not require
-     * or control the encryption of any other storage areas.
-     * There is one exception:  If {@link android.os.Environment#isExternalStorageEmulated()} is
-     * {@code true}, then the directory returned by
-     * {@link android.os.Environment#getExternalStorageDirectory()} must be written to disk
-     * within the encrypted storage area.
-     *
-     * <p>Important Note:  On some devices, it is possible to encrypt storage without requiring
-     * the user to create a device PIN or Password.  In this case, the storage is encrypted, but
-     * the encryption key may not be fully secured.  For maximum security, the administrator should
-     * also require (and check for) a pattern, PIN, or password.
+     * <p>
+     * This policy controls encryption of the secure (application data) storage area. Data written
+     * to other storage areas may or may not be encrypted, and this policy does not require or
+     * control the encryption of any other storage areas. There is one exception: If
+     * {@link android.os.Environment#isExternalStorageEmulated()} is {@code true}, then the
+     * directory returned by {@link android.os.Environment#getExternalStorageDirectory()} must be
+     * written to disk within the encrypted storage area.
+     * <p>
+     * Important Note: On some devices, it is possible to encrypt storage without requiring the user
+     * to create a device PIN or Password. In this case, the storage is encrypted, but the
+     * encryption key may not be fully secured. For maximum security, the administrator should also
+     * require (and check for) a pattern, PIN, or password.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param encrypt true to request encryption, false to release any previous request
      * @return the new request status (for all active admins) - will be one of
-     * {@link #ENCRYPTION_STATUS_UNSUPPORTED}, {@link #ENCRYPTION_STATUS_INACTIVE}, or
-     * {@link #ENCRYPTION_STATUS_ACTIVE}.  This is the value of the requests;  Use
-     * {@link #getStorageEncryptionStatus()} to query the actual device state.
+     *         {@link #ENCRYPTION_STATUS_UNSUPPORTED}, {@link #ENCRYPTION_STATUS_INACTIVE}, or
+     *         {@link #ENCRYPTION_STATUS_ACTIVE}. This is the value of the requests; Use
+     *         {@link #getStorageEncryptionStatus()} to query the actual device state.
+     * @throws SecurityException if {@code admin} is not an active administrator or does not use
+     *             {@link DeviceAdminInfo#USES_ENCRYPTED_STORAGE}
      */
     public int setStorageEncryption(@NonNull ComponentName admin, boolean encrypt) {
         if (mService != null) {
@@ -2627,7 +2628,7 @@
     public int getStorageEncryptionStatus(int userHandle) {
         if (mService != null) {
             try {
-                return mService.getStorageEncryptionStatus(userHandle);
+                return mService.getStorageEncryptionStatus(mContext.getPackageName(), userHandle);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -2644,6 +2645,8 @@
      *
      * @return false if the certBuffer cannot be parsed or installation is
      *         interrupted, true otherwise.
+     * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
+     *         owner.
      */
     public boolean installCaCert(@Nullable ComponentName admin, byte[] certBuffer) {
         if (mService != null) {
@@ -2662,6 +2665,8 @@
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
      *              {@code null} if calling from a delegated certificate installer.
      * @param certBuffer encoded form of the certificate to remove.
+     * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
+     *         owner.
      */
     public void uninstallCaCert(@Nullable ComponentName admin, byte[] certBuffer) {
         if (mService != null) {
@@ -2684,6 +2689,8 @@
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
      *              {@code null} if calling from a delegated certificate installer.
      * @return a List of byte[] arrays, each encoding one user CA certificate.
+     * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
+     *         owner.
      */
     public List<byte[]> getInstalledCaCerts(@Nullable ComponentName admin) {
         List<byte[]> certs = new ArrayList<byte[]>();
@@ -2711,6 +2718,8 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
      *              {@code null} if calling from a delegated certificate installer.
+     * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
+     *         owner.
      */
     public void uninstallAllUserCaCerts(@Nullable ComponentName admin) {
         if (mService != null) {
@@ -2729,6 +2738,8 @@
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
      *              {@code null} if calling from a delegated certificate installer.
      * @param certBuffer encoded form of the certificate to look up.
+     * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
+     *         owner.
      */
     public boolean hasCaCertInstalled(@Nullable ComponentName admin, byte[] certBuffer) {
         if (mService != null) {
@@ -2763,6 +2774,8 @@
      * @param alias The private key alias under which to install the certificate. If a certificate
      * with that alias already exists, it will be overwritten.
      * @return {@code true} if the keys were installed, {@code false} otherwise.
+     * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
+     *         owner.
      */
     public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
             @NonNull Certificate cert, @NonNull String alias) {
@@ -2788,6 +2801,8 @@
      *        credentials immediately. Otherwise, access to the credentials will be gated by user
      *        approval.
      * @return {@code true} if the keys were installed, {@code false} otherwise.
+     * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
+     *         owner.
      */
     public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey,
             @NonNull Certificate cert, @NonNull String alias, boolean requestAccess) {
@@ -2814,6 +2829,8 @@
      *        {@code null} if calling from a delegated certificate installer.
      * @param alias The private key alias under which the certificate is installed.
      * @return {@code true} if the private key alias no longer exists, {@code false} otherwise.
+     * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile
+     *         owner.
      */
     public boolean removeKeyPair(@Nullable ComponentName admin, @NonNull String alias) {
         try {
@@ -2843,15 +2860,16 @@
      * Delegated certificate installer is a per-user state. The delegated access is persistent until
      * it is later cleared by calling this method with a null value or uninstallling the certificate
      * installer.
-     *<p>
+     * <p>
      * <b>Note:</b>Starting from {@link android.os.Build.VERSION_CODES#N}, if the caller
      * application's target SDK version is {@link android.os.Build.VERSION_CODES#N} or newer, the
-     * supplied certificate installer package must be installed when calling this API,
-     * otherwise an {@link IllegalArgumentException} will be thrown.
+     * supplied certificate installer package must be installed when calling this API, otherwise an
+     * {@link IllegalArgumentException} will be thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param installerPackage The package name of the certificate installer which will be given
-     * access. If {@code null} is given the current package will be cleared.
+     *            access. If {@code null} is given the current package will be cleared.
+     * @throws SecurityException if {@code admin} is not a device or a profile owner.
      */
     public void setCertInstallerPackage(@NonNull ComponentName admin, @Nullable String
             installerPackage) throws SecurityException {
@@ -2865,12 +2883,13 @@
     }
 
     /**
-     * Called by a profile owner or device owner to retrieve the certificate installer for the
-     * user. null if none is set.
+     * Called by a profile owner or device owner to retrieve the certificate installer for the user.
+     * null if none is set.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @return The package name of the current delegated certificate installer, or {@code null}
-     * if none is set.
+     * @return The package name of the current delegated certificate installer, or {@code null} if
+     *         none is set.
+     * @throws SecurityException if {@code admin} is not a device or a profile owner.
      */
     public String getCertInstallerPackage(@NonNull ComponentName admin) throws SecurityException {
         if (mService != null) {
@@ -2885,18 +2904,18 @@
 
     /**
      * Called by a device or profile owner to configure an always-on VPN connection through a
-     * specific application for the current user.
-     * This connection is automatically granted and persisted after a reboot.
+     * specific application for the current user. This connection is automatically granted and
+     * persisted after a reboot.
+     * <p>
+     * The designated package should declare a {@link android.net.VpnService} in its manifest
+     * guarded by {@link android.Manifest.permission#BIND_VPN_SERVICE}, otherwise the call will
+     * fail.
      *
-     * <p>The designated package should declare a {@link android.net.VpnService} in its
-     *    manifest guarded by {@link android.Manifest.permission#BIND_VPN_SERVICE},
-     *    otherwise the call will fail.
-     *
-     * @param vpnPackage The package name for an installed VPN app on the device, or {@code null}
-     *                   to remove an existing always-on VPN configuration.
-     *
-     * @return {@code true} if the package is set as always-on VPN controller;
-     *         {@code false} otherwise.
+     * @param vpnPackage The package name for an installed VPN app on the device, or {@code null} to
+     *            remove an existing always-on VPN configuration.
+     * @return {@code true} if the package is set as always-on VPN controller; {@code false}
+     *         otherwise.
+     * @throws SecurityException if {@code admin} is not a device or a profile owner.
      */
     public boolean setAlwaysOnVpnPackage(@NonNull ComponentName admin,
             @Nullable String vpnPackage) {
@@ -2912,12 +2931,12 @@
 
     /**
      * Called by a device or profile owner to read the name of the package administering an
-     * always-on VPN connection for the current user.
-     * If there is no such package, or the always-on VPN is provided by the system instead
-     * of by an application, {@code null} will be returned.
+     * always-on VPN connection for the current user. If there is no such package, or the always-on
+     * VPN is provided by the system instead of by an application, {@code null} will be returned.
      *
-     * @return Package name of VPN controller responsible for always-on VPN,
-     *         or {@code null} if none is set.
+     * @return Package name of VPN controller responsible for always-on VPN, or {@code null} if none
+     *         is set.
+     * @throws SecurityException if {@code admin} is not a device or a profile owner.
      */
     public String getAlwaysOnVpnPackage(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -2931,18 +2950,20 @@
     }
 
     /**
-     * Called by an application that is administering the device to disable all cameras
-     * on the device, for this user. After setting this, no applications running as this user
-     * will be able to access any cameras on the device.
-     *
-     * <p>If the caller is device owner, then the restriction will be applied to all users.
-     *
-     * <p>The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA} to be able to call
-     * this method; if it has not, a security exception will be thrown.
+     * Called by an application that is administering the device to disable all cameras on the
+     * device, for this user. After setting this, no applications running as this user will be able
+     * to access any cameras on the device.
+     * <p>
+     * If the caller is device owner, then the restriction will be applied to all users.
+     * <p>
+     * The calling device admin must have requested
+     * {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA} to be able to call this method; if it has
+     * not, a security exception will be thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param disabled Whether or not the camera should be disabled.
+     * @throws SecurityException if {@code admin} is not an active administrator or does not use
+     *             {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA}.
      */
     public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) {
         if (mService != null) {
@@ -2978,14 +2999,16 @@
 
     /**
      * Called by a device owner to request a bugreport.
-     *
-     * <p>There must be only one user on the device, managed by the device owner.
-     * Otherwise a {@link SecurityException} will be thrown.
+     * <p>
+     * There must be only one user on the device, managed by the device owner. Otherwise a
+     * {@link SecurityException} will be thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @return {@code true} if the bugreport collection started successfully, or {@code false}
-     * if it wasn't triggered because a previous bugreport operation is still active
-     * (either the bugreport is still running or waiting for the user to share or decline)
+     * @return {@code true} if the bugreport collection started successfully, or {@code false} if it
+     *         wasn't triggered because a previous bugreport operation is still active (either the
+     *         bugreport is still running or waiting for the user to share or decline)
+     * @throws SecurityException if {@code admin} is not a device owner, or if there are users other
+     *             than the one managed by the device owner.
      */
     public boolean requestBugreport(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -3014,15 +3037,16 @@
      * screen capture also prevents the content from being shown on display devices that do not have
      * a secure video output. See {@link android.view.Display#FLAG_SECURE} for more details about
      * secure surfaces and secure displays.
-     *
-     * <p>The calling device admin must be a device or profile owner. If it is not, a
-     * security exception will be thrown.
-     *
-     * <p>From version {@link android.os.Build.VERSION_CODES#M} disabling screen capture also
-     * blocks assist requests for all activities of the relevant user.
+     * <p>
+     * The calling device admin must be a device or profile owner. If it is not, a security
+     * exception will be thrown.
+     * <p>
+     * From version {@link android.os.Build.VERSION_CODES#M} disabling screen capture also blocks
+     * assist requests for all activities of the relevant user.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param disabled Whether screen capture is disabled or not.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setScreenCaptureDisabled(@NonNull ComponentName admin, boolean disabled) {
         if (mService != null) {
@@ -3057,16 +3081,17 @@
     }
 
     /**
-     * Called by a device owner to set whether auto time is required. If auto time is
-     * required the user cannot set the date and time, but has to use network date and time.
-     *
-     * <p>Note: if auto time is required the user can still manually set the time zone.
-     *
-     * <p>The calling device admin must be a device owner. If it is not, a security exception will
-     * be thrown.
+     * Called by a device owner to set whether auto time is required. If auto time is required the
+     * user cannot set the date and time, but has to use network date and time.
+     * <p>
+     * Note: if auto time is required the user can still manually set the time zone.
+     * <p>
+     * The calling device admin must be a device owner. If it is not, a security exception will be
+     * thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param required Whether auto time is set required or not.
+     * @throws SecurityException if {@code admin} is not a device owner.
      */
     public void setAutoTimeRequired(@NonNull ComponentName admin, boolean required) {
         if (mService != null) {
@@ -3094,15 +3119,16 @@
 
     /**
      * Called by a device owner to set whether all users created on the device should be ephemeral.
-     *
-     * <p>The system user is exempt from this policy - it is never ephemeral.
-     *
-     * <p>The calling device admin must be the device owner. If it is not, a security exception will
-     * be thrown.
+     * <p>
+     * The system user is exempt from this policy - it is never ephemeral.
+     * <p>
+     * The calling device admin must be the device owner. If it is not, a security exception will be
+     * thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param forceEphemeralUsers If true, all the existing users will be deleted and all
-     *         subsequently created users will be ephemeral.
+     *            subsequently created users will be ephemeral.
+     * @throws SecurityException if {@code admin} is not a device owner.
      * @hide
      */
     public void setForceEphemeralUsers(
@@ -3118,6 +3144,7 @@
 
     /**
      * @return true if all users are created ephemeral.
+     * @throws SecurityException if {@code admin} is not a device owner.
      * @hide
      */
     public boolean getForceEphemeralUsers(@NonNull ComponentName admin) {
@@ -3135,39 +3162,41 @@
      * Called by an application that is administering the device to disable keyguard customizations,
      * such as widgets. After setting this, keyguard features will be disabled according to the
      * provided feature list.
-     *
-     * <p>The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call
-     * this method; if it has not, a security exception will be thrown.
-     *
-     * <p>Calling this from a managed profile before version
-     * {@link android.os.Build.VERSION_CODES#M} will throw a security exception. From version
-     * {@link android.os.Build.VERSION_CODES#M} the profile owner of a managed profile can set:
+     * <p>
+     * The calling device admin must have requested
+     * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call this method;
+     * if it has not, a security exception will be thrown.
+     * <p>
+     * Calling this from a managed profile before version {@link android.os.Build.VERSION_CODES#M}
+     * will throw a security exception. From version {@link android.os.Build.VERSION_CODES#M} the
+     * profile owner of a managed profile can set:
      * <ul>
      * <li>{@link #KEYGUARD_DISABLE_TRUST_AGENTS}, which affects the parent user, but only if there
-     *      is no separate challenge set on the managed profile.
+     * is no separate challenge set on the managed profile.
      * <li>{@link #KEYGUARD_DISABLE_FINGERPRINT} which affects the managed profile challenge if
-     *      there is one, or the parent user otherwise.
-     * <li>{@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS} which affects notifications
-     *      generated by applications in the managed profile.
+     * there is one, or the parent user otherwise.
+     * <li>{@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS} which affects notifications generated
+     * by applications in the managed profile.
      * </ul>
-     *
      * {@link #KEYGUARD_DISABLE_TRUST_AGENTS} and {@link #KEYGUARD_DISABLE_FINGERPRINT} can also be
      * set on the {@link DevicePolicyManager} instance returned by
-     * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the
-     * parent profile.
-     *
-     * <p>Requests to disable other features on a managed profile will be ignored.
-     *
-     * <p>The admin can check which features have been disabled by calling
+     * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
+     * profile.
+     * <p>
+     * Requests to disable other features on a managed profile will be ignored.
+     * <p>
+     * The admin can check which features have been disabled by calling
      * {@link #getKeyguardDisabledFeatures(ComponentName)}
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param which {@link #KEYGUARD_DISABLE_FEATURES_NONE} (default),
-     * {@link #KEYGUARD_DISABLE_WIDGETS_ALL}, {@link #KEYGUARD_DISABLE_SECURE_CAMERA},
-     * {@link #KEYGUARD_DISABLE_SECURE_NOTIFICATIONS}, {@link #KEYGUARD_DISABLE_TRUST_AGENTS},
-     * {@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS}, {@link #KEYGUARD_DISABLE_FINGERPRINT},
-     * {@link #KEYGUARD_DISABLE_FEATURES_ALL}
+     *            {@link #KEYGUARD_DISABLE_WIDGETS_ALL}, {@link #KEYGUARD_DISABLE_SECURE_CAMERA},
+     *            {@link #KEYGUARD_DISABLE_SECURE_NOTIFICATIONS},
+     *            {@link #KEYGUARD_DISABLE_TRUST_AGENTS},
+     *            {@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS},
+     *            {@link #KEYGUARD_DISABLE_FINGERPRINT}, {@link #KEYGUARD_DISABLE_FEATURES_ALL}
+     * @throws SecurityException if {@code admin} is not an active administrator or does not user
+     *             {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES}
      */
     public void setKeyguardDisabledFeatures(@NonNull ComponentName admin, int which) {
         if (mService != null) {
@@ -3494,13 +3523,13 @@
     }
 
     /**
-     * Clears the current device owner.  The caller must be the device owner.
-     *
-     * This function should be used cautiously as once it is called it cannot
-     * be undone.  The device owner can only be set as a part of device setup
-     * before setup completes.
+     * Clears the current device owner. The caller must be the device owner. This function should be
+     * used cautiously as once it is called it cannot be undone. The device owner can only be set as
+     * a part of device setup before setup completes.
      *
      * @param packageName The package name of the device owner.
+     * @throws SecurityException if the caller is not in {@code packageName} or {@code packageName}
+     *             does not own the current device owner component.
      */
     public void clearDeviceOwnerApp(String packageName) {
         if (mService != null) {
@@ -3610,13 +3639,14 @@
     }
 
     /**
-     * Clears the active profile owner and removes all user restrictions. The caller must
-     * be from the same package as the active profile owner for this user, otherwise a
-     * SecurityException will be thrown.
-     *
-     * <p>This doesn't work for managed profile owners.
+     * Clears the active profile owner and removes all user restrictions. The caller must be from
+     * the same package as the active profile owner for this user, otherwise a SecurityException
+     * will be thrown.
+     * <p>
+     * This doesn't work for managed profile owners.
      *
      * @param admin The component to remove as the profile owner.
+     * @throws SecurityException if {@code admin} is not an active profile owner.
      */
     public void clearProfileOwner(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -3676,20 +3706,21 @@
 
     /**
      * Sets the device owner information to be shown on the lock screen.
-     *
-     * <p>If the device owner information is {@code null} or empty then the device owner info is
+     * <p>
+     * If the device owner information is {@code null} or empty then the device owner info is
      * cleared and the user owner info is shown on the lock screen if it is set.
-     * <p>If the device owner information contains only whitespaces then the message on the lock
-     * screen will be blank and the user will not be allowed to change it.
-     *
-     * <p>If the device owner information needs to be localized, it is the responsibility of the
+     * <p>
+     * If the device owner information contains only whitespaces then the message on the lock screen
+     * will be blank and the user will not be allowed to change it.
+     * <p>
+     * If the device owner information needs to be localized, it is the responsibility of the
      * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
      * and set a new version of this string accordingly.
      *
      * @param admin The name of the admin component to check.
-     * @param info Device owner information which will be displayed instead of the user
-     * owner info.
+     * @param info Device owner information which will be displayed instead of the user owner info.
      * @return Whether the device owner information has been set.
+     * @throws SecurityException if {@code admin} is not a device owner.
      */
     public boolean setDeviceOwnerLockScreenInfo(@NonNull ComponentName admin, String info) {
         if (mService != null) {
@@ -3718,19 +3749,22 @@
 
     /**
      * Called by device or profile owners to suspend packages for this user.
-     *
-     * <p>A suspended package will not be able to start activities. Its notifications will
-     * be hidden, it will not show up in recents, will not be able to show toasts or dialogs
-     * or ring the device.
-     *
-     * <p>The package must already be installed.
+     * <p>
+     * A suspended package will not be able to start activities. Its notifications will be hidden,
+     * it will not show up in recents, will not be able to show toasts or dialogs or ring the
+     * device.
+     * <p>
+     * The package must already be installed. If the package is uninstalled while suspended the
+     * package will no longer be suspended. The admin can block this by using
+     * {@link #setUninstallBlocked}.
      *
      * @param admin The name of the admin component to check.
      * @param packageNames The package names to suspend or unsuspend.
      * @param suspended If set to {@code true} than the packages will be suspended, if set to
-     * {@code false} the packages will be unsuspended.
+     *            {@code false} the packages will be unsuspended.
      * @return an array of package names for which the suspended status is not set as requested in
-     * this method.
+     *         this method.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public String[] setPackagesSuspended(@NonNull ComponentName admin, String[] packageNames,
             boolean suspended) {
@@ -3750,7 +3784,8 @@
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param packageName The name of the package to retrieve the suspended status of.
      * @return {@code true} if the package is suspended or {@code false} if the package is not
-     * suspended, could not be found or an error occurred.
+     *         suspended, could not be found or an error occurred.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean getPackageSuspended(@NonNull ComponentName admin, String packageName) {
         if (mService != null) {
@@ -3768,8 +3803,8 @@
      * be used. Only the profile owner can call this.
      *
      * @see #isProfileOwnerApp
-     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public void setProfileEnabled(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -3782,15 +3817,15 @@
     }
 
     /**
-     * Sets the name of the profile. In the device owner case it sets the name of the user
-     * which it is called from. Only a profile owner or device owner can call this. If this is
-     * never called by the profile or device owner, the name will be set to default values.
+     * Sets the name of the profile. In the device owner case it sets the name of the user which it
+     * is called from. Only a profile owner or device owner can call this. If this is never called
+     * by the profile or device owner, the name will be set to default values.
      *
      * @see #isProfileOwnerApp
      * @see #isDeviceOwnerApp
-     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associate with.
      * @param profileName The name of the profile.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setProfileName(@NonNull ComponentName admin, String profileName) {
         if (mService != null) {
@@ -3888,19 +3923,20 @@
     /**
      * Called by a profile owner or device owner to add a default intent handler activity for
      * intents that match a certain intent filter. This activity will remain the default intent
-     * handler even if the set of potential event handlers for the intent filter changes and if
-     * the intent preferences are reset.
-     *
-     * <p>The default disambiguation mechanism takes over if the activity is not installed
-     * (anymore). When the activity is (re)installed, it is automatically reset as default
-     * intent handler for the filter.
-     *
-     * <p>The calling device admin must be a profile owner or device owner. If it is not, a
-     * security exception will be thrown.
+     * handler even if the set of potential event handlers for the intent filter changes and if the
+     * intent preferences are reset.
+     * <p>
+     * The default disambiguation mechanism takes over if the activity is not installed (anymore).
+     * When the activity is (re)installed, it is automatically reset as default intent handler for
+     * the filter.
+     * <p>
+     * The calling device admin must be a profile owner or device owner. If it is not, a security
+     * exception will be thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param filter The IntentFilter for which a default handler is added.
      * @param activity The Activity that is added as default intent handler.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void addPersistentPreferredActivity(@NonNull ComponentName admin, IntentFilter filter,
             @NonNull ComponentName activity) {
@@ -3916,12 +3952,13 @@
     /**
      * Called by a profile owner or device owner to remove all persistent intent handler preferences
      * associated with the given package that were set by {@link #addPersistentPreferredActivity}.
-     *
-     * <p>The calling device admin must be a profile owner. If it is not, a security
-     * exception will be thrown.
+     * <p>
+     * The calling device admin must be a profile owner. If it is not, a security exception will be
+     * thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param packageName The name of the package for which preferences are removed.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void clearPackagePersistentPreferredActivities(@NonNull ComponentName admin,
             String packageName) {
@@ -3947,7 +3984,8 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param packageName The package name which will be given access to application restrictions
-     * APIs. If {@code null} is given the current package will be cleared.
+     *            APIs. If {@code null} is given the current package will be cleared.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setApplicationRestrictionsManagingPackage(@NonNull ComponentName admin,
             @Nullable String packageName) {
@@ -3966,7 +4004,8 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @return The package name allowed to manage application restrictions on the current user, or
-     * {@code null} if none is set.
+     *         {@code null} if none is set.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public String getApplicationRestrictionsManagingPackage(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -3980,9 +4019,12 @@
     }
 
     /**
-     * Returns {@code true} if the calling package has been granted permission via
-     * {@link #setApplicationRestrictionsManagingPackage} to manage application
-     * restrictions for the calling user.
+     * Called by any application to find out whether it has been granted permission via
+     * {@link #setApplicationRestrictionsManagingPackage} to manage application restrictions
+     * for the calling user.
+     *
+     * <p>This is done by comparing the calling Linux uid with the uid of the package specified by
+     * that method.
      */
     public boolean isCallerApplicationRestrictionsManagingPackage() {
         if (mService != null) {
@@ -3997,34 +4039,34 @@
 
     /**
      * Sets the application restrictions for a given target application running in the calling user.
-     *
-     * <p>The caller must be a profile or device owner on that user, or the package allowed to
-     * manage application restrictions via {@link #setApplicationRestrictionsManagingPackage};
-     * otherwise a security exception will be thrown.
-     *
-     * <p>The provided {@link Bundle} consists of key-value pairs, where the types of values may be:
+     * <p>
+     * The caller must be a profile or device owner on that user, or the package allowed to manage
+     * application restrictions via {@link #setApplicationRestrictionsManagingPackage}; otherwise a
+     * security exception will be thrown.
+     * <p>
+     * The provided {@link Bundle} consists of key-value pairs, where the types of values may be:
      * <ul>
      * <li>{@code boolean}
      * <li>{@code int}
      * <li>{@code String} or {@code String[]}
      * <li>From {@link android.os.Build.VERSION_CODES#M}, {@code Bundle} or {@code Bundle[]}
      * </ul>
-     *
-     * <p>If the restrictions are not available yet, but may be applied in the near future,
-     * the caller can notify the target application of that by adding
+     * <p>
+     * If the restrictions are not available yet, but may be applied in the near future, the caller
+     * can notify the target application of that by adding
      * {@link UserManager#KEY_RESTRICTIONS_PENDING} to the settings parameter.
-     *
-     * <p>The application restrictions are only made visible to the target application via
-     * {@link UserManager#getApplicationRestrictions(String)}, in addition to the profile or
-     * device owner, and the application restrictions managing package via
+     * <p>
+     * The application restrictions are only made visible to the target application via
+     * {@link UserManager#getApplicationRestrictions(String)}, in addition to the profile or device
+     * owner, and the application restrictions managing package via
      * {@link #getApplicationRestrictions}.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
-     * {@code null} if called by the application restrictions managing package.
+     *            {@code null} if called by the application restrictions managing package.
      * @param packageName The name of the package to update restricted settings for.
      * @param settings A {@link Bundle} to be parsed by the receiving application, conveying a new
-     * set of active restrictions.
-     *
+     *            set of active restrictions.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      * @see #setApplicationRestrictionsManagingPackage
      * @see UserManager#KEY_RESTRICTIONS_PENDING
      */
@@ -4040,23 +4082,29 @@
     }
 
     /**
-     * Sets a list of configuration features to enable for a TrustAgent component. This is meant
-     * to be used in conjunction with {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, which disables all
-     * trust agents but those enabled by this function call. If flag
+     * Sets a list of configuration features to enable for a TrustAgent component. This is meant to
+     * be used in conjunction with {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, which disables all trust
+     * agents but those enabled by this function call. If flag
      * {@link #KEYGUARD_DISABLE_TRUST_AGENTS} is not set, then this call has no effect.
-     *
-     * <p>The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call
-     * this method; if not, a security exception will be thrown.
+     * <p>
+     * The calling device admin must have requested
+     * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call this method;
+     * if not, a security exception will be thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param target Component name of the agent to be enabled.
-     * @param configuration TrustAgent-specific feature bundle. If null for any admin, agent
-     * will be strictly disabled according to the state of the
-     *  {@link #KEYGUARD_DISABLE_TRUST_AGENTS} flag.
-     * <p>If {@link #KEYGUARD_DISABLE_TRUST_AGENTS} is set and options is not null for all admins,
-     * then it's up to the TrustAgent itself to aggregate the values from all device admins.
-     * <p>Consult documentation for the specific TrustAgent to determine legal options parameters.
+     * @param configuration TrustAgent-specific feature bundle. If null for any admin, agent will be
+     *            strictly disabled according to the state of the
+     *            {@link #KEYGUARD_DISABLE_TRUST_AGENTS} flag.
+     *            <p>
+     *            If {@link #KEYGUARD_DISABLE_TRUST_AGENTS} is set and options is not null for all
+     *            admins, then it's up to the TrustAgent itself to aggregate the values from all
+     *            device admins.
+     *            <p>
+     *            Consult documentation for the specific TrustAgent to determine legal options
+     *            parameters.
+     * @throws SecurityException if {@code admin} is not an active administrator or does not use
+     *             {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES}
      */
     public void setTrustAgentConfiguration(@NonNull ComponentName admin,
             @NonNull ComponentName target, PersistableBundle configuration) {
@@ -4102,14 +4150,15 @@
     }
 
     /**
-     * Called by a profile owner of a managed profile to set whether caller-Id information from
-     * the managed profile will be shown in the parent profile, for incoming calls.
-     *
-     * <p>The calling device admin must be a profile owner. If it is not, a
-     * security exception will be thrown.
+     * Called by a profile owner of a managed profile to set whether caller-Id information from the
+     * managed profile will be shown in the parent profile, for incoming calls.
+     * <p>
+     * The calling device admin must be a profile owner. If it is not, a security exception will be
+     * thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param disabled If true caller-Id information in the managed profile is not displayed.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setCrossProfileCallerIdDisabled(@NonNull ComponentName admin, boolean disabled) {
         if (mService != null) {
@@ -4124,11 +4173,12 @@
     /**
      * Called by a profile owner of a managed profile to determine whether or not caller-Id
      * information has been disabled.
-     *
-     * <p>The calling device admin must be a profile owner. If it is not, a
-     * security exception will be thrown.
+     * <p>
+     * The calling device admin must be a profile owner. If it is not, a security exception will be
+     * thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean getCrossProfileCallerIdDisabled(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -4159,14 +4209,15 @@
     }
 
     /**
-     * Called by a profile owner of a managed profile to set whether contacts search from
-     * the managed profile will be shown in the parent profile, for incoming calls.
-     *
-     * <p>The calling device admin must be a profile owner. If it is not, a
-     * security exception will be thrown.
+     * Called by a profile owner of a managed profile to set whether contacts search from the
+     * managed profile will be shown in the parent profile, for incoming calls.
+     * <p>
+     * The calling device admin must be a profile owner. If it is not, a security exception will be
+     * thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param disabled If true contacts search in the managed profile is not displayed.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setCrossProfileContactsSearchDisabled(@NonNull ComponentName admin,
             boolean disabled) {
@@ -4182,11 +4233,12 @@
     /**
      * Called by a profile owner of a managed profile to determine whether or not contacts search
      * has been disabled.
-     *
-     * <p>The calling device admin must be a profile owner. If it is not, a
-     * security exception will be thrown.
+     * <p>
+     * The calling device admin must be a profile owner. If it is not, a security exception will be
+     * thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean getCrossProfileContactsSearchDisabled(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -4246,18 +4298,17 @@
     }
 
     /**
-     * Called by a profile owner of a managed profile to set whether bluetooth
-     * devices can access enterprise contacts.
+     * Called by a profile owner of a managed profile to set whether bluetooth devices can access
+     * enterprise contacts.
      * <p>
-     * The calling device admin must be a profile owner. If it is not, a
-     * security exception will be thrown.
+     * The calling device admin must be a profile owner. If it is not, a security exception will be
+     * thrown.
      * <p>
      * This API works on managed profile only.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated
-     *            with.
-     * @param disabled If true, bluetooth devices cannot access enterprise
-     *            contacts.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param disabled If true, bluetooth devices cannot access enterprise contacts.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setBluetoothContactSharingDisabled(@NonNull ComponentName admin, boolean disabled) {
         if (mService != null) {
@@ -4270,16 +4321,16 @@
     }
 
     /**
-     * Called by a profile owner of a managed profile to determine whether or
-     * not Bluetooth devices cannot access enterprise contacts.
+     * Called by a profile owner of a managed profile to determine whether or not Bluetooth devices
+     * cannot access enterprise contacts.
      * <p>
-     * The calling device admin must be a profile owner. If it is not, a
-     * security exception will be thrown.
+     * The calling device admin must be a profile owner. If it is not, a security exception will be
+     * thrown.
      * <p>
      * This API works on managed profile only.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated
-     *            with.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean getBluetoothContactSharingDisabled(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -4314,14 +4365,15 @@
 
     /**
      * Called by the profile owner of a managed profile so that some intents sent in the managed
-     * profile can also be resolved in the parent, or vice versa.
-     * Only activity intents are supported.
+     * profile can also be resolved in the parent, or vice versa. Only activity intents are
+     * supported.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param filter The {@link IntentFilter} the intent has to match to be also resolved in the
-     * other profile
+     *            other profile
      * @param flags {@link DevicePolicyManager#FLAG_MANAGED_CAN_ACCESS_PARENT} and
-     * {@link DevicePolicyManager#FLAG_PARENT_CAN_ACCESS_MANAGED} are supported.
+     *            {@link DevicePolicyManager#FLAG_PARENT_CAN_ACCESS_MANAGED} are supported.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void addCrossProfileIntentFilter(@NonNull ComponentName admin, IntentFilter filter, int flags) {
         if (mService != null) {
@@ -4337,7 +4389,9 @@
      * Called by a profile owner of a managed profile to remove the cross-profile intent filters
      * that go from the managed profile to the parent, or from the parent to the managed profile.
      * Only removes those that have been set by the profile owner.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void clearCrossProfileIntentFilters(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -4350,25 +4404,22 @@
     }
 
     /**
-     * Called by a profile or device owner to set the permitted accessibility services. When
-     * set by a device owner or profile owner the restriction applies to all profiles of the
-     * user the device owner or profile owner is an admin for.
-     *
-     * By default the user can use any accessiblity service. When zero or more packages have
-     * been added, accessiblity services that are not in the list and not part of the system
-     * can not be enabled by the user.
-     *
-     * <p> Calling with a null value for the list disables the restriction so that all services
-     * can be used, calling with an empty list only allows the builtin system's services.
-     *
-     * <p> System accesibility services are always available to the user the list can't modify
-     * this.
+     * Called by a profile or device owner to set the permitted accessibility services. When set by
+     * a device owner or profile owner the restriction applies to all profiles of the user the
+     * device owner or profile owner is an admin for. By default the user can use any accessiblity
+     * service. When zero or more packages have been added, accessiblity services that are not in
+     * the list and not part of the system can not be enabled by the user.
+     * <p>
+     * Calling with a null value for the list disables the restriction so that all services can be
+     * used, calling with an empty list only allows the builtin system's services.
+     * <p>
+     * System accesibility services are always available to the user the list can't modify this.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param packageNames List of accessibility service package names.
-     *
-     * @return true if setting the restriction succeeded. It fail if there is
-     * one or more non-system accessibility services enabled, that are not in the list.
+     * @return true if setting the restriction succeeded. It fail if there is one or more non-system
+     *         accessibility services enabled, that are not in the list.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean setPermittedAccessibilityServices(@NonNull ComponentName admin,
             List<String> packageNames) {
@@ -4384,12 +4435,13 @@
 
     /**
      * Returns the list of permitted accessibility services set by this device or profile owner.
-     *
-     * <p>An empty list means no accessibility services except system services are allowed.
-     * Null means all accessibility services are allowed.
+     * <p>
+     * An empty list means no accessibility services except system services are allowed. Null means
+     * all accessibility services are allowed.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @return List of accessiblity service package names.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public List<String> getPermittedAccessibilityServices(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -4450,27 +4502,23 @@
      }
 
     /**
-     * Called by a profile or device owner to set the permitted input methods services. When
-     * set by a device owner or profile owner the restriction applies to all profiles of the
-     * user the device owner or profile owner is an admin for.
-     *
-     * By default the user can use any input method. When zero or more packages have
-     * been added, input method that are not in the list and not part of the system
-     * can not be enabled by the user.
-     *
-     * This method will fail if it is called for a admin that is not for the foreground user
-     * or a profile of the foreground user.
-     *
-     * <p> Calling with a null value for the list disables the restriction so that all input methods
-     * can be used, calling with an empty list disables all but the system's own input methods.
-     *
-     * <p> System input methods are always available to the user this method can't modify this.
+     * Called by a profile or device owner to set the permitted input methods services. When set by
+     * a device owner or profile owner the restriction applies to all profiles of the user the
+     * device owner or profile owner is an admin for. By default the user can use any input method.
+     * When zero or more packages have been added, input method that are not in the list and not
+     * part of the system can not be enabled by the user. This method will fail if it is called for
+     * a admin that is not for the foreground user or a profile of the foreground user.
+     * <p>
+     * Calling with a null value for the list disables the restriction so that all input methods can
+     * be used, calling with an empty list disables all but the system's own input methods.
+     * <p>
+     * System input methods are always available to the user this method can't modify this.
      *
      * @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 are
-     *     one or more non-system input methods currently enabled that are not in
-     *     the packageNames list.
+     * @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.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean setPermittedInputMethods(@NonNull ComponentName admin, List<String> packageNames) {
         if (mService != null) {
@@ -4486,12 +4534,13 @@
 
     /**
      * Returns the list of permitted input methods set by this device or profile owner.
-     *
-     * <p>An empty list means no input methods except system input methods are allowed.
-     * Null means all input methods are allowed.
+     * <p>
+     * An empty list means no input methods except system input methods are allowed. Null means all
+     * input methods are allowed.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @return List of input method package names.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public List<String> getPermittedInputMethods(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -4578,6 +4627,7 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param packageNames List of package names to keep cached.
+     * @throws SecurityException if {@code admin} is not a device owner.
      * @hide
      */
     public void setKeepUninstalledPackages(@NonNull ComponentName admin,
@@ -4663,27 +4713,27 @@
      * persisted as user handles are recycled as users are removed and created. If you need to
      * persist an identifier for this user, use {@link UserManager#getSerialNumberForUser}. The new
      * user will not be started in the background.
-     *
-     * <p>admin is the {@link DeviceAdminReceiver} which is the device owner. profileOwner is also
-     * a DeviceAdminReceiver in the same package as admin, and will become the profile owner and
-     * will be registered as an active admin on the new user. The profile owner package will be
-     * installed on the new user.
-     *
-     * <p>If the adminExtras are not null, they will be stored on the device until the user is
-     * started for the first time. Then the extras will be passed to the admin when
-     * onEnable is called.
+     * <p>
+     * admin is the {@link DeviceAdminReceiver} which is the device owner. profileOwner is also a
+     * DeviceAdminReceiver in the same package as admin, and will become the profile owner and will
+     * be registered as an active admin on the new user. The profile owner package will be installed
+     * on the new user.
+     * <p>
+     * If the adminExtras are not null, they will be stored on the device until the user is started
+     * for the first time. Then the extras will be passed to the admin when onEnable is called.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param name The user's name.
      * @param profileOwner Which {@link DeviceAdminReceiver} will be profile owner. Has to be in the
-     *      same package as admin, otherwise no user is created and an IllegalArgumentException is
-     *      thrown.
+     *            same package as admin, otherwise no user is created and an
+     *            IllegalArgumentException is thrown.
      * @param adminExtras Extras that will be passed to onEnable of the admin receiver on the new
-     *      user.
+     *            user.
      * @param flags {@link #SKIP_SETUP_WIZARD} is supported.
      * @see UserHandle
      * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the
      *         user could not be created.
+     * @throws SecurityException if {@code admin} is not a device owner.
      */
     public UserHandle createAndManageUser(@NonNull ComponentName admin, @NonNull String name,
             @NonNull ComponentName profileOwner, @Nullable PersistableBundle adminExtras,
@@ -4696,12 +4746,13 @@
     }
 
     /**
-     * Called by a device owner to remove a user and all associated data. The primary user can
-     * not be removed.
+     * Called by a device owner to remove a user and all associated data. The primary user can not
+     * be removed.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param userHandle the user to remove.
      * @return {@code true} if the user was removed, {@code false} otherwise.
+     * @throws SecurityException if {@code admin} is not a device owner.
      */
     public boolean removeUser(@NonNull ComponentName admin, UserHandle userHandle) {
         try {
@@ -4717,7 +4768,7 @@
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param userHandle the user to switch to; null will switch to primary.
      * @return {@code true} if the switch was successful, {@code false} otherwise.
-     *
+     * @throws SecurityException if {@code admin} is not a device owner.
      * @see Intent#ACTION_USER_FOREGROUND
      */
     public boolean switchUser(@NonNull ComponentName admin, @Nullable UserHandle userHandle) {
@@ -4731,18 +4782,18 @@
     /**
      * Retrieves the application restrictions for a given target application running in the calling
      * user.
-     *
-     * <p>The caller must be a profile or device owner on that user, or the package allowed to
-     * manage application restrictions via {@link #setApplicationRestrictionsManagingPackage};
-     * otherwise a security exception will be thrown.
+     * <p>
+     * The caller must be a profile or device owner on that user, or the package allowed to manage
+     * application restrictions via {@link #setApplicationRestrictionsManagingPackage}; otherwise a
+     * security exception will be thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
-     * {@code null} if called by the application restrictions managing package.
+     *            {@code null} if called by the application restrictions managing package.
      * @param packageName The name of the package to fetch restricted settings of.
      * @return {@link Bundle} of settings corresponding to what was set last time
-     * {@link DevicePolicyManager#setApplicationRestrictions} was called, or an empty {@link Bundle}
-     * if no restrictions have been set.
-     *
+     *         {@link DevicePolicyManager#setApplicationRestrictions} was called, or an empty
+     *         {@link Bundle} if no restrictions have been set.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      * @see {@link #setApplicationRestrictionsManagingPackage}
      */
     public Bundle getApplicationRestrictions(@Nullable ComponentName admin, String packageName) {
@@ -4759,13 +4810,13 @@
     /**
      * Called by a profile or device owner to set a user restriction specified by the key.
      * <p>
-     * The calling device admin must be a profile or device owner; if it is not,
-     * a security exception will be thrown.
+     * The calling device admin must be a profile or device owner; if it is not, a security
+     * exception will be thrown.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated
-     *            with.
-     * @param key The key of the restriction. See the constants in
-     *            {@link android.os.UserManager} for the list of keys.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param key The key of the restriction. See the constants in {@link android.os.UserManager}
+     *            for the list of keys.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void addUserRestriction(@NonNull ComponentName admin, String key) {
         if (mService != null) {
@@ -4780,13 +4831,13 @@
     /**
      * Called by a profile or device owner to clear a user restriction specified by the key.
      * <p>
-     * The calling device admin must be a profile or device owner; if it is not,
-     * a security exception will be thrown.
+     * The calling device admin must be a profile or device owner; if it is not, a security
+     * exception will be thrown.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated
-     *            with.
-     * @param key The key of the restriction. See the constants in
-     *            {@link android.os.UserManager} for the list of keys.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param key The key of the restriction. See the constants in {@link android.os.UserManager}
+     *            for the list of keys.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void clearUserRestriction(@NonNull ComponentName admin, String key) {
         if (mService != null) {
@@ -4803,11 +4854,11 @@
      * {@link #addUserRestriction(ComponentName, String)}.
      * <p>
      * The target user may have more restrictions set by the system or other device owner / profile
-     * owner.  To get all the user restrictions currently set, use
+     * owner. To get all the user restrictions currently set, use
      * {@link UserManager#getUserRestrictions()}.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @throws SecurityException if the {@code admin} is not an active admin.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public Bundle getUserRestrictions(@NonNull ComponentName admin) {
         return getUserRestrictions(admin, myUserId());
@@ -4827,14 +4878,15 @@
     }
 
     /**
-     * Called by profile or device owners to hide or unhide packages. When a package is hidden it
-     * is unavailable for use, but the data and actual package file remain.
+     * Called by profile or device owners to hide or unhide packages. When a package is hidden it is
+     * unavailable for use, but the data and actual package file remain.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param packageName The name of the package to hide or unhide.
      * @param hidden {@code true} if the package should be hidden, {@code false} if it should be
-     *                 unhidden.
+     *            unhidden.
      * @return boolean Whether the hidden setting of the package was successfully updated.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean setApplicationHidden(@NonNull ComponentName admin, String packageName,
             boolean hidden) {
@@ -4854,6 +4906,7 @@
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param packageName The name of the package to retrieve the hidden status of.
      * @return boolean {@code true} if the package is hidden, {@code false} otherwise.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean isApplicationHidden(@NonNull ComponentName admin, String packageName) {
         if (mService != null) {
@@ -4872,6 +4925,7 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param packageName The package to be re-enabled in the calling profile.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void enableSystemApp(@NonNull ComponentName admin, String packageName) {
         if (mService != null) {
@@ -4884,13 +4938,14 @@
     }
 
     /**
-     * Called by profile or device owners to re-enable system apps by intent that were disabled
-     * by default when the user was initialized.
+     * Called by profile or device owners to re-enable system apps by intent that were disabled by
+     * default when the user was initialized.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param intent An intent matching the app(s) to be installed. All apps that resolve for this
-     *               intent will be re-enabled in the calling profile.
+     *            intent will be re-enabled in the calling profile.
      * @return int The number of activities that matched the intent and were installed.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public int enableSystemApp(@NonNull ComponentName admin, Intent intent) {
         if (mService != null) {
@@ -4906,21 +4961,22 @@
     /**
      * Called by a device owner or profile owner to disable account management for a specific type
      * of account.
-     *
-     * <p>The calling device admin must be a device owner or profile owner. If it is not, a
-     * security exception will be thrown.
-     *
-     * <p>When account management is disabled for an account type, adding or removing an account
-     * of that type will not be possible.
-     *
-     * <p>From {@link android.os.Build.VERSION_CODES#N} the profile or device owner can still use
+     * <p>
+     * The calling device admin must be a device owner or profile owner. If it is not, a security
+     * exception will be thrown.
+     * <p>
+     * When account management is disabled for an account type, adding or removing an account of
+     * that type will not be possible.
+     * <p>
+     * From {@link android.os.Build.VERSION_CODES#N} the profile or device owner can still use
      * {@link android.accounts.AccountManager} APIs to add or remove accounts when account
      * management for a specific type is disabled.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param accountType For which account management is disabled or enabled.
      * @param disabled The boolean indicating that account management will be disabled (true) or
-     * enabled (false).
+     *            enabled (false).
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setAccountManagementDisabled(@NonNull ComponentName admin, String accountType,
             boolean disabled) {
@@ -4965,17 +5021,15 @@
 
     /**
      * Sets which packages may enter lock task mode.
+     * <p>
+     * Any packages that shares uid with an allowed package will also be allowed to activate lock
+     * task. From {@link android.os.Build.VERSION_CODES#M} removing packages from the lock task
+     * package list results in locked tasks belonging to those packages to be finished. This
+     * function can only be called by the device owner.
      *
-     * <p>Any packages that shares uid with an allowed package will also be allowed
-     * to activate lock task.
-     *
-     * From {@link android.os.Build.VERSION_CODES#M} removing packages from the lock task
-     * package list results in locked tasks belonging to those packages to be finished.
-     *
-     * This function can only be called by the device owner.
      * @param packages The list of packages allowed to enter lock task mode
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     *
+     * @throws SecurityException if {@code admin} is not a device owner.
      * @see Activity#startLockTask()
      * @see DeviceAdminReceiver#onLockTaskModeEntering(Context, Intent, String)
      * @see DeviceAdminReceiver#onLockTaskModeExiting(Context, Intent)
@@ -5028,7 +5082,8 @@
     /**
      * Called by device owners to update {@link Settings.Global} settings. Validation that the value
      * of the setting is in the correct form for the setting type should be performed by the caller.
-     * <p>The settings that can be updated with this method are:
+     * <p>
+     * The settings that can be updated with this method are:
      * <ul>
      * <li>{@link Settings.Global#ADB_ENABLED}</li>
      * <li>{@link Settings.Global#AUTO_TIME}</li>
@@ -5036,30 +5091,30 @@
      * <li>{@link Settings.Global#DATA_ROAMING}</li>
      * <li>{@link Settings.Global#USB_MASS_STORAGE_ENABLED}</li>
      * <li>{@link Settings.Global#WIFI_SLEEP_POLICY}</li>
-     * <li>{@link Settings.Global#STAY_ON_WHILE_PLUGGED_IN}
-     *   This setting is only available from {@link android.os.Build.VERSION_CODES#M} onwards
-     *   and can only be set if {@link #setMaximumTimeToLock} is not used to set a timeout.</li>
-     * <li>{@link Settings.Global#WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN}</li>
-     *   This setting is only available from {@link android.os.Build.VERSION_CODES#M} onwards.
-     *   </li>
+     * <li>{@link Settings.Global#STAY_ON_WHILE_PLUGGED_IN} This setting is only available from
+     * {@link android.os.Build.VERSION_CODES#M} onwards and can only be set if
+     * {@link #setMaximumTimeToLock} is not used to set a timeout.</li>
+     * <li>{@link Settings.Global#WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN}</li> This setting is only
+     * available from {@link android.os.Build.VERSION_CODES#M} onwards.</li>
      * </ul>
-     * <p>Changing the following settings has no effect as of
-     * {@link android.os.Build.VERSION_CODES#M}:
+     * <p>
+     * Changing the following settings has no effect as of {@link android.os.Build.VERSION_CODES#M}:
      * <ul>
-     * <li>{@link Settings.Global#BLUETOOTH_ON}.
-     *   Use {@link android.bluetooth.BluetoothAdapter#enable()} and
-     *   {@link android.bluetooth.BluetoothAdapter#disable()} instead.</li>
+     * <li>{@link Settings.Global#BLUETOOTH_ON}. Use
+     * {@link android.bluetooth.BluetoothAdapter#enable()} and
+     * {@link android.bluetooth.BluetoothAdapter#disable()} instead.</li>
      * <li>{@link Settings.Global#DEVELOPMENT_SETTINGS_ENABLED}</li>
-     * <li>{@link Settings.Global#MODE_RINGER}.
-     *   Use {@link android.media.AudioManager#setRingerMode(int)} instead.</li>
+     * <li>{@link Settings.Global#MODE_RINGER}. Use
+     * {@link android.media.AudioManager#setRingerMode(int)} instead.</li>
      * <li>{@link Settings.Global#NETWORK_PREFERENCE}</li>
-     * <li>{@link Settings.Global#WIFI_ON}.
-     *   Use {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} instead.</li>
+     * <li>{@link Settings.Global#WIFI_ON}. Use
+     * {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} instead.</li>
      * </ul>
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param setting The name of the setting to update.
      * @param value The value to update the setting to.
+     * @throws SecurityException if {@code admin} is not a device owner.
      */
     public void setGlobalSetting(@NonNull ComponentName admin, String setting, String value) {
         if (mService != null) {
@@ -5075,19 +5130,23 @@
      * Called by profile or device owners to update {@link Settings.Secure} settings. Validation
      * that the value of the setting is in the correct form for the setting type should be performed
      * by the caller.
-     * <p>The settings that can be updated by a profile or device owner with this method are:
+     * <p>
+     * The settings that can be updated by a profile or device owner with this method are:
      * <ul>
      * <li>{@link Settings.Secure#DEFAULT_INPUT_METHOD}</li>
      * <li>{@link Settings.Secure#INSTALL_NON_MARKET_APPS}</li>
      * <li>{@link Settings.Secure#SKIP_FIRST_USE_HINTS}</li>
      * </ul>
-     * <p>A device owner can additionally update the following settings:
+     * <p>
+     * A device owner can additionally update the following settings:
      * <ul>
      * <li>{@link Settings.Secure#LOCATION_MODE}</li>
      * </ul>
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param setting The name of the setting to update.
      * @param value The value to update the setting to.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setSecureSetting(@NonNull ComponentName admin, String setting, String value) {
         if (mService != null) {
@@ -5100,14 +5159,16 @@
     }
 
     /**
-     * Designates a specific service component as the provider for
-     * making permission requests of a local or remote administrator of the user.
+     * Designates a specific service component as the provider for making permission requests of a
+     * local or remote administrator of the user.
      * <p/>
      * Only a profile owner can designate the restrictions provider.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param provider The component name of the service that implements
-     * {@link RestrictionsReceiver}. If this param is null,
-     * it removes the restrictions provider previously assigned.
+     *            {@link RestrictionsReceiver}. If this param is null, it removes the restrictions
+     *            provider previously assigned.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setRestrictionsProvider(@NonNull ComponentName admin,
             @Nullable ComponentName provider) {
@@ -5125,6 +5186,7 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param on {@code true} to mute master volume, {@code false} to turn mute off.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setMasterVolumeMuted(@NonNull ComponentName admin, boolean on) {
         if (mService != null) {
@@ -5141,6 +5203,7 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @return {@code true} if master volume is muted, {@code false} if it's not.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean isMasterVolumeMuted(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -5154,12 +5217,12 @@
     }
 
     /**
-     * Called by profile or device owners to change whether a user can uninstall
-     * a package.
+     * Called by profile or device owners to change whether a user can uninstall a package.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param packageName package to change.
      * @param uninstallBlocked true if the user shouldn't be able to uninstall the package.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setUninstallBlocked(@NonNull ComponentName admin, String packageName,
             boolean uninstallBlocked) {
@@ -5177,14 +5240,15 @@
      * Requires the caller to be the profile owner if checking a specific admin's policy.
      * <p>
      * <strong>Note:</strong> Starting from {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}, the
-     * behavior of this API is changed such that passing {@code null} as the {@code admin}
-     * parameter will return if any admin has blocked the uninstallation. Before L MR1, passing
-     * {@code null} will cause a NullPointerException to be raised.
+     * behavior of this API is changed such that passing {@code null} as the {@code admin} parameter
+     * will return if any admin has blocked the uninstallation. Before L MR1, passing {@code null}
+     * will cause a NullPointerException to be raised.
      *
      * @param admin The name of the admin component whose blocking policy will be checked, or
-     *              {@code null} to check whether any admin has blocked the uninstallation.
+     *            {@code null} to check whether any admin has blocked the uninstallation.
      * @param packageName package to check.
      * @return true if uninstallation is blocked.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public boolean isUninstallBlocked(@Nullable ComponentName admin, String packageName) {
         if (mService != null) {
@@ -5198,19 +5262,18 @@
     }
 
     /**
-     * Called by the profile owner of a managed profile to enable widget providers from a
-     * given package to be available in the parent profile. As a result the user will be able to
-     * add widgets from the white-listed package running under the profile to a widget
-     * host which runs under the parent profile, for example the home screen. Note that
-     * a package may have zero or more provider components, where each component
-     * provides a different widget type.
+     * Called by the profile owner of a managed profile to enable widget providers from a given
+     * package to be available in the parent profile. As a result the user will be able to add
+     * widgets from the white-listed package running under the profile to a widget host which runs
+     * under the parent profile, for example the home screen. Note that a package may have zero or
+     * more provider components, where each component provides a different widget type.
      * <p>
      * <strong>Note:</strong> By default no widget provider package is white-listed.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param packageName The package from which widget providers are white-listed.
      * @return Whether the package was added.
-     *
+     * @throws SecurityException if {@code admin} is not a profile owner.
      * @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String)
      * @see #getCrossProfileWidgetProviders(android.content.ComponentName)
      */
@@ -5227,17 +5290,16 @@
 
     /**
      * Called by the profile owner of a managed profile to disable widget providers from a given
-     * package to be available in the parent profile. For this method to take effect the
-     * package should have been added via {@link #addCrossProfileWidgetProvider(
-     * android.content.ComponentName, String)}.
+     * package to be available in the parent profile. For this method to take effect the package
+     * should have been added via
+     * {@link #addCrossProfileWidgetProvider( android.content.ComponentName, String)}.
      * <p>
      * <strong>Note:</strong> By default no widget provider package is white-listed.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @param packageName The package from which widget providers are no longer
-     *     white-listed.
+     * @param packageName The package from which widget providers are no longer white-listed.
      * @return Whether the package was removed.
-     *
+     * @throws SecurityException if {@code admin} is not a profile owner.
      * @see #addCrossProfileWidgetProvider(android.content.ComponentName, String)
      * @see #getCrossProfileWidgetProviders(android.content.ComponentName)
      */
@@ -5259,9 +5321,9 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @return The white-listed package list.
-     *
      * @see #addCrossProfileWidgetProvider(android.content.ComponentName, String)
      * @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String)
+     * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public List<String> getCrossProfileWidgetProviders(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -5282,6 +5344,7 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param icon the bitmap to set as the photo.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      */
     public void setUserIcon(@NonNull ComponentName admin, Bitmap icon) {
         try {
@@ -5296,10 +5359,10 @@
      * {@link #ACTION_SYSTEM_UPDATE_POLICY_CHANGED} is broadcasted.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with. All
-     *              components in the device owner package can set system update policies and the
-     *              most recent policy takes
-     * effect.
+     *            components in the device owner package can set system update policies and the most
+     *            recent policy takes effect.
      * @param policy the new policy, or {@code null} to clear the current policy.
+     * @throws SecurityException if {@code admin} is not a device owner.
      * @see SystemUpdatePolicy
      */
     public void setSystemUpdatePolicy(@NonNull ComponentName admin, SystemUpdatePolicy policy) {
@@ -5330,17 +5393,17 @@
 
     /**
      * Called by a device owner to disable the keyguard altogether.
-     *
-     * <p>Setting the keyguard to disabled has the same effect as choosing "None" as the screen
-     * lock type. However, this call has no effect if a password, pin or pattern is currently set.
-     * If a password, pin or pattern is set after the keyguard was disabled, the keyguard stops
-     * being disabled.
+     * <p>
+     * Setting the keyguard to disabled has the same effect as choosing "None" as the screen lock
+     * type. However, this call has no effect if a password, pin or pattern is currently set. If a
+     * password, pin or pattern is set after the keyguard was disabled, the keyguard stops being
+     * disabled.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param disabled {@code true} disables the keyguard, {@code false} reenables it.
-     *
      * @return {@code false} if attempting to disable the keyguard while a lock password was in
-     * place. {@code true} otherwise.
+     *         place. {@code true} otherwise.
+     * @throws SecurityException if {@code admin} is not a device owner.
      */
     public boolean setKeyguardDisabled(@NonNull ComponentName admin, boolean disabled) {
         try {
@@ -5352,14 +5415,13 @@
 
     /**
      * Called by device owner to disable the status bar. Disabling the status bar blocks
-     * notifications, quick settings and other screen overlays that allow escaping from
-     * a single use device.
+     * notifications, quick settings and other screen overlays that allow escaping from a single use
+     * device.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param disabled {@code true} disables the status bar, {@code false} reenables it.
-     *
-     * @return {@code false} if attempting to disable the status bar failed.
-     * {@code true} otherwise.
+     * @return {@code false} if attempting to disable the status bar failed. {@code true} otherwise.
+     * @throws SecurityException if {@code admin} is not a device owner.
      */
     public boolean setStatusBarDisabled(@NonNull ComponentName admin, boolean disabled) {
         try {
@@ -5391,19 +5453,19 @@
 
     /**
      * Called by profile or device owners to set the default response for future runtime permission
-     * requests by applications. The policy can allow for normal operation which prompts the
-     * user to grant a permission, or can allow automatic granting or denying of runtime
-     * permission requests by an application. This also applies to new permissions declared by app
-     * updates. When a permission is denied or granted this way, the effect is equivalent to setting
-     * the permission grant state via {@link #setPermissionGrantState}.
-     *
-     * <p/>As this policy only acts on runtime permission requests, it only applies to applications
+     * requests by applications. The policy can allow for normal operation which prompts the user to
+     * grant a permission, or can allow automatic granting or denying of runtime permission requests
+     * by an application. This also applies to new permissions declared by app updates. When a
+     * permission is denied or granted this way, the effect is equivalent to setting the permission
+     * grant state via {@link #setPermissionGrantState}.
+     * <p/>
+     * As this policy only acts on runtime permission requests, it only applies to applications
      * built with a {@code targetSdkVersion} of {@link android.os.Build.VERSION_CODES#M} or later.
      *
      * @param admin Which profile or device owner this request is associated with.
      * @param policy One of the policy constants {@link #PERMISSION_POLICY_PROMPT},
-     * {@link #PERMISSION_POLICY_AUTO_GRANT} and {@link #PERMISSION_POLICY_AUTO_DENY}.
-     *
+     *            {@link #PERMISSION_POLICY_AUTO_GRANT} and {@link #PERMISSION_POLICY_AUTO_DENY}.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      * @see #setPermissionGrantState
      */
     public void setPermissionPolicy(@NonNull ComponentName admin, int policy) {
@@ -5429,29 +5491,28 @@
     }
 
     /**
-     * Sets the grant state of a runtime permission for a specific application. The state
-     * can be {@link #PERMISSION_GRANT_STATE_DEFAULT default} in which a user can manage it
-     * through the UI, {@link #PERMISSION_GRANT_STATE_DENIED denied}, in which the permission
-     * is denied and the user cannot manage it through the UI, and {@link
-     * #PERMISSION_GRANT_STATE_GRANTED granted} in which the permission is granted and the
-     * user cannot manage it through the UI. This might affect all permissions in a
-     * group that the runtime permission belongs to. This method can only be called
+     * Sets the grant state of a runtime permission for a specific application. The state can be
+     * {@link #PERMISSION_GRANT_STATE_DEFAULT default} in which a user can manage it through the UI,
+     * {@link #PERMISSION_GRANT_STATE_DENIED denied}, in which the permission is denied and the user
+     * cannot manage it through the UI, and {@link #PERMISSION_GRANT_STATE_GRANTED granted} in which
+     * the permission is granted and the user cannot manage it through the UI. This might affect all
+     * permissions in a group that the runtime permission belongs to. This method can only be called
      * by a profile or device owner.
-     *
-     * <p/>Setting the grant state to {@link #PERMISSION_GRANT_STATE_DEFAULT default} does not
-     * revoke the permission. It retains the previous grant, if any.
-     *
-     * <p/>Permissions can be granted or revoked only for applications built with a
+     * <p/>
+     * Setting the grant state to {@link #PERMISSION_GRANT_STATE_DEFAULT default} does not revoke
+     * the permission. It retains the previous grant, if any.
+     * <p/>
+     * Permissions can be granted or revoked only for applications built with a
      * {@code targetSdkVersion} of {@link android.os.Build.VERSION_CODES#M} or later.
      *
      * @param admin Which profile or device owner this request is associated with.
      * @param packageName The application to grant or revoke a permission to.
      * @param permission The permission to grant or revoke.
-     * @param grantState The permission grant state which is one of {@link
-     *         #PERMISSION_GRANT_STATE_DENIED}, {@link #PERMISSION_GRANT_STATE_DEFAULT},
-     *         {@link #PERMISSION_GRANT_STATE_GRANTED},
+     * @param grantState The permission grant state which is one of
+     *            {@link #PERMISSION_GRANT_STATE_DENIED}, {@link #PERMISSION_GRANT_STATE_DEFAULT},
+     *            {@link #PERMISSION_GRANT_STATE_GRANTED},
      * @return whether the permission was successfully granted or revoked.
-     *
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      * @see #PERMISSION_GRANT_STATE_DENIED
      * @see #PERMISSION_GRANT_STATE_DEFAULT
      * @see #PERMISSION_GRANT_STATE_GRANTED
@@ -5472,13 +5533,15 @@
      * @param packageName The application to check the grant state for.
      * @param permission The permission to check for.
      * @return the current grant state specified by device policy. If the profile or device owner
-     * has not set a grant state, the return value is {@link #PERMISSION_GRANT_STATE_DEFAULT}.
-     * This does not indicate whether or not the permission is currently granted for the package.
-     *
-     * <p/>If a grant state was set by the profile or device owner, then the return value will
-     * be one of {@link #PERMISSION_GRANT_STATE_DENIED} or {@link #PERMISSION_GRANT_STATE_GRANTED},
-     * which indicates if the permission is currently denied or granted.
-     *
+     *         has not set a grant state, the return value is
+     *         {@link #PERMISSION_GRANT_STATE_DEFAULT}. This does not indicate whether or not the
+     *         permission is currently granted for the package.
+     *         <p/>
+     *         If a grant state was set by the profile or device owner, then the return value will
+     *         be one of {@link #PERMISSION_GRANT_STATE_DENIED} or
+     *         {@link #PERMISSION_GRANT_STATE_GRANTED}, which indicates if the permission is
+     *         currently denied or granted.
+     * @throws SecurityException if {@code admin} is not a device or profile owner.
      * @see #setPermissionGrantState(ComponentName, String, String, int)
      * @see PackageManager#checkPermission(String, String)
      */
@@ -5495,9 +5558,6 @@
      * Returns if provisioning a managed profile or device is possible or not.
      * @param action One of {@link #ACTION_PROVISION_MANAGED_DEVICE},
      * {@link #ACTION_PROVISION_MANAGED_PROFILE}.
-     * Note that even if this method returns true, there is a slight possibility that the
-     * provisioning will not be allowed when it is actually initiated because some event has
-     * happened in between.
      * @return if provisioning a managed profile or device is possible or not.
      * @throws IllegalArgumentException if the supplied action is not valid.
      */
@@ -5544,10 +5604,11 @@
      * Called by device owner to get the MAC address of the Wi-Fi device.
      *
      * @param admin Which device owner this request is associated with.
-     * @return the MAC address of the Wi-Fi device, or null when the information is not
-     * available. (For example, Wi-Fi hasn't been enabled, or the device doesn't support Wi-Fi.)
-     *
-     * <p>The address will be in the {@code XX:XX:XX:XX:XX:XX} format.
+     * @return the MAC address of the Wi-Fi device, or null when the information is not available.
+     *         (For example, Wi-Fi hasn't been enabled, or the device doesn't support Wi-Fi.)
+     *         <p>
+     *         The address will be in the {@code XX:XX:XX:XX:XX:XX} format.
+     * @throws SecurityException if {@code admin} is not a device owner.
      */
     public String getWifiMacAddress(@NonNull ComponentName admin) {
         try {
@@ -5558,7 +5619,12 @@
     }
 
     /**
-     * Called by device owner to reboot the device.
+     * Called by device owner to reboot the device. If there is an ongoing call on the device,
+     * throws an {@link IllegalStateException}.
+     * @param admin Which device owner the request is associated with.
+     * @throws IllegalStateException if device has an ongoing call.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     * @see TelephonyManager#CALL_STATE_IDLE
      */
     public void reboot(@NonNull ComponentName admin) {
         try {
@@ -5569,24 +5635,21 @@
     }
 
     /**
-     * Called by a device admin to set the short support message. This will
-     * be displayed to the user in settings screens where funtionality has
-     * been disabled by the admin.
-     *
-     * The message should be limited to a short statement such as
-     * "This setting is disabled by your administrator. Contact someone@example.com
-     *  for support."
-     * If the message is longer than 200 characters it may be truncated.
-     *
-     * <p>If the short support message needs to be localized, it is the responsibility of the
+     * Called by a device admin to set the short support message. This will be displayed to the user
+     * in settings screens where funtionality has been disabled by the admin. The message should be
+     * limited to a short statement such as "This setting is disabled by your administrator. Contact
+     * someone@example.com for support." If the message is longer than 200 characters it may be
+     * truncated.
+     * <p>
+     * If the short support message needs to be localized, it is the responsibility of the
      * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
      * and set a new version of this string accordingly.
      *
      * @see #setLongSupportMessage
-     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @param message Short message to be displayed to the user in settings or null to
-     *        clear the existing message.
+     * @param message Short message to be displayed to the user in settings or null to clear the
+     *            existing message.
+     * @throws SecurityException if {@code admin} is not an active administrator.
      */
     public void setShortSupportMessage(@NonNull ComponentName admin,
             @Nullable String message) {
@@ -5603,8 +5666,9 @@
      * Called by a device admin to get the short support message.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @return The message set by {@link #setShortSupportMessage(ComponentName, String)}
-     *         or null if no message has been set.
+     * @return The message set by {@link #setShortSupportMessage(ComponentName, String)} or null if
+     *         no message has been set.
+     * @throws SecurityException if {@code admin} is not an active administrator.
      */
     public String getShortSupportMessage(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -5618,18 +5682,18 @@
     }
 
     /**
-     * Called by a device admin to set the long support message. This will
-     * be displayed to the user in the device administators settings screen.
-     *
-     * <p>If the long support message needs to be localized, it is the responsibility of the
+     * Called by a device admin to set the long support message. This will be displayed to the user
+     * in the device administators settings screen.
+     * <p>
+     * If the long support message needs to be localized, it is the responsibility of the
      * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
      * and set a new version of this string accordingly.
      *
      * @see #setShortSupportMessage
-     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @param message Long message to be displayed to the user in settings or null to
-     *        clear the existing message.
+     * @param message Long message to be displayed to the user in settings or null to clear the
+     *            existing message.
+     * @throws SecurityException if {@code admin} is not an active administrator.
      */
     public void setLongSupportMessage(@NonNull ComponentName admin,
             @Nullable String message) {
@@ -5646,8 +5710,9 @@
      * Called by a device admin to get the long support message.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
-     * @return The message set by {@link #setLongSupportMessage(ComponentName, String)}
-     *         or null if no message has been set.
+     * @return The message set by {@link #setLongSupportMessage(ComponentName, String)} or null if
+     *         no message has been set.
+     * @throws SecurityException if {@code admin} is not an active administrator.
      */
     public String getLongSupportMessage(@NonNull ComponentName admin) {
         if (mService != null) {
@@ -5704,10 +5769,11 @@
     /**
      * Called by the profile owner of a managed profile to obtain a {@link DevicePolicyManager}
      * whose calls act on the parent profile.
-     *
-     * <p> Note only some methods will work on the parent Manager.
+     * <p>
+     * Note only some methods will work on the parent Manager.
      *
      * @return a new instance of {@link DevicePolicyManager} that acts on the parent profile.
+     * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public DevicePolicyManager getParentProfileInstance(@NonNull ComponentName admin) {
         try {
@@ -5721,46 +5787,64 @@
     }
 
     /**
-     * Called by device owner to control the device logging feature. Logging can only be
+     * Called by device owner to control the security logging feature. Logging can only be
      * enabled on single user devices where the sole user is managed by the device owner.
      *
-     * <p> Device logs contain various information intended for security auditing purposes.
+     * <p> Security logs contain various information intended for security auditing purposes.
      * See {@link SecurityEvent} for details.
      *
      * <p>There must be only one user on the device, managed by the device owner.
      * Otherwise a {@link SecurityException} will be thrown.
      *
      * @param admin Which device owner this request is associated with.
-     * @param enabled whether device logging should be enabled or not.
-     * @see #retrieveDeviceLogs
+     * @param enabled whether security logging should be enabled or not.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     * @see #retrieveSecurityLogs
      */
-    public void setDeviceLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
+    public void setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
         try {
-            mService.setDeviceLoggingEnabled(admin, enabled);
+            mService.setSecurityLoggingEnabled(admin, enabled);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Return whether device logging is enabled or not by the device owner.
+     * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+     * @hide
+     */
+    public void setDeviceLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
+        setSecurityLoggingEnabled(admin, enabled);
+    }
+
+    /**
+     * Return whether security logging is enabled or not by the device owner.
      *
      * <p>Can only be called by the device owner, otherwise a {@link SecurityException} will be
      * thrown.
      *
      * @param admin Which device owner this request is associated with.
-     * @return {@code true} if device logging is enabled by device owner, {@code false} otherwise.
+     * @return {@code true} if security logging is enabled by device owner, {@code false} otherwise.
+     * @throws SecurityException if {@code admin} is not a device owner.
      */
-    public boolean getDeviceLoggingEnabled(@NonNull ComponentName admin) {
+    public boolean isSecurityLoggingEnabled(@NonNull ComponentName admin) {
         try {
-            return mService.getDeviceLoggingEnabled(admin);
+            return mService.isSecurityLoggingEnabled(admin);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Called by device owner to retrieve all new device logging entries since the last call to
+     * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+     * @hide
+     */
+    public boolean getDeviceLoggingEnabled(@NonNull ComponentName admin) {
+        return isSecurityLoggingEnabled(admin);
+    }
+
+    /**
+     * Called by device owner to retrieve all new security logging entries since the last call to
      * this API after device boots.
      *
      * <p> Access to the logs is rate limited and it will only return new logs after the device
@@ -5770,12 +5854,13 @@
      * Otherwise a {@link SecurityException} will be thrown.
      *
      * @param admin Which device owner this request is associated with.
-     * @return the new batch of device logs which is a list of {@link SecurityEvent},
+     * @return the new batch of security logs which is a list of {@link SecurityEvent},
      * or {@code null} if rate limitation is exceeded or if logging is currently disabled.
+     * @throws SecurityException if {@code admin} is not a device owner.
      */
-    public List<SecurityEvent> retrieveDeviceLogs(@NonNull ComponentName admin) {
+    public List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) {
         try {
-            ParceledListSlice<SecurityEvent> list = mService.retrieveDeviceLogs(admin);
+            ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(admin);
             if (list != null) {
                 return list.getList();
             } else {
@@ -5788,6 +5873,14 @@
     }
 
     /**
+     * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+     * @hide
+     */
+    public List<SecurityEvent> retrieveDeviceLogs(@NonNull ComponentName admin) {
+        return retrieveSecurityLogs(admin);
+    }
+
+    /**
      * Called by the system to obtain a {@link DevicePolicyManager} whose calls act on the parent
      * profile.
      *
@@ -5805,22 +5898,22 @@
 
     /**
      * Called by device owners to retrieve device logs from before the device's last reboot.
-     *
      * <p>
      * <strong> The device logs are retrieved from a RAM region which is not guaranteed to be
-     * corruption-free during power cycles, due to hardware variations and limitations. As a
-     * result, this API is provided as best-effort and the returned logs may contain corrupted data.
-     * </strong>
-     *
-     * <p>There must be only one user on the device, managed by the device owner.
-     * Otherwise a {@link SecurityException} will be thrown.
+     * corruption-free during power cycles, due to hardware variations and limitations. As a result,
+     * this API is provided as best-effort and the returned logs may contain corrupted
+     * data. </strong>
+     * <p>
+     * There must be only one user on the device, managed by the device owner. Otherwise a
+     * {@link SecurityException} will be thrown.
      *
      * @param admin Which device owner this request is associated with.
      * @return Device logs from before the latest reboot of the system.
+     * @throws SecurityException if {@code admin} is not a device owner.
      */
-    public List<SecurityEvent> retrievePreviousDeviceLogs(@NonNull ComponentName admin) {
+    public List<SecurityEvent> retrievePreRebootSecurityLogs(@NonNull ComponentName admin) {
         try {
-            ParceledListSlice<SecurityEvent> list = mService.retrievePreviousDeviceLogs(admin);
+            ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(admin);
             return list.getList();
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
@@ -5828,15 +5921,24 @@
     }
 
     /**
-     * Called by a profile owner of a managed profile to set the color used for customization.
-     * This color is used as background color of the confirm credentials screen for that user.
-     * The default color is {@link android.graphics.Color#GRAY}.
-     *
-     * <p>The confirm credentials screen can be created using
+     * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
+     * @hide
+     */
+    public List<SecurityEvent> retrievePreviousDeviceLogs(@NonNull ComponentName admin) {
+        return retrievePreRebootSecurityLogs(admin);
+    }
+
+    /**
+     * Called by a profile owner of a managed profile to set the color used for customization. This
+     * color is used as background color of the confirm credentials screen for that user. The
+     * default color is {@link android.graphics.Color#GRAY}.
+     * <p>
+     * The confirm credentials screen can be created using
      * {@link android.app.KeyguardManager#createConfirmDeviceCredentialIntent}.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param color The 32bit representation of the color to be used.
+     * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public void setOrganizationColor(@NonNull ComponentName admin, int color) {
         try {
@@ -5871,6 +5973,7 @@
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @return The 32bit representation of the color to be used.
+     * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public int getOrganizationColor(@NonNull ComponentName admin) {
         try {
@@ -5898,13 +6001,14 @@
     /**
      * Called by a profile owner of a managed profile to set the name of the organization under
      * management.
-     *
-     * <p>If the organization name needs to be localized, it is the responsibility of the
+     * <p>
+     * If the organization name needs to be localized, it is the responsibility of the
      * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
      * and set a new version of this string accordingly.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param title The organization name or {@code null} to clear a previously set name.
+     * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public void setOrganizationName(@NonNull ComponentName admin, @Nullable String title) {
         try {
@@ -5915,11 +6019,12 @@
     }
 
     /**
-     * Called by a profile owner of a managed profile to retrieve the name of the organization
-     * under management.
+     * Called by a profile owner of a managed profile to retrieve the name of the organization under
+     * management.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @return The organization name or {@code null} if none is set.
+     * @throws SecurityException if {@code admin} is not a profile owner.
      */
     public String getOrganizationName(@NonNull ComponentName admin) {
         try {
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 8cdfee5..54a2f7a 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -16,6 +16,9 @@
 
 package android.app.admin;
 
+import android.content.Intent;
+import android.os.UserHandle;
+
 import java.util.List;
 
 /**
@@ -71,11 +74,24 @@
     public abstract boolean isActiveAdminWithPolicy(int uid, int reqPolicy);
 
     /**
-     * Checks if a given package has a device or a profile owner for the given user
+     * Checks if a given package has a device or a profile owner for the given user.
+     * <p>
+     * <em>Note: does <b>not</b> support negative userIds like {@link UserHandle#USER_ALL}</em>
      *
      * @param packageName The package to check
      * @param userId the userId to check for.
      * @return true if package has a device or profile owner, false otherwise.
      */
     public abstract boolean hasDeviceOwnerOrProfileOwner(String packageName, int userId);
+
+    /**
+     * Creates an intent to show the admin support dialog to let the user know that the package is
+     * suspended by the admin. This assumes that {@param packageName} is suspended by the
+     * device/profile owner. The caller should check if the package is suspended or not.
+     *
+     * @param packageName The package that is suspended
+     * @param userId The user having the suspended package.
+     * @return The intent to trigger the admin support dialog.
+     */
+    public abstract Intent createPackageSuspendedDialogIntent(String packageName, int userId);
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index dc73e26..3ba5bd8 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -91,7 +91,7 @@
 
     int setStorageEncryption(in ComponentName who, boolean encrypt);
     boolean getStorageEncryption(in ComponentName who, int userHandle);
-    int getStorageEncryptionStatus(int userHandle);
+    int getStorageEncryptionStatus(in String callerPackage, int userHandle);
 
     boolean requestBugreport(in ComponentName who);
 
@@ -290,10 +290,10 @@
     void setAffiliationIds(in ComponentName admin, in List<String> ids);
     boolean isAffiliatedUser();
 
-    void setDeviceLoggingEnabled(in ComponentName admin, boolean enabled);
-    boolean getDeviceLoggingEnabled(in ComponentName admin);
-    ParceledListSlice retrieveDeviceLogs(in ComponentName admin);
-    ParceledListSlice retrievePreviousDeviceLogs(in ComponentName admin);
+    void setSecurityLoggingEnabled(in ComponentName admin, boolean enabled);
+    boolean isSecurityLoggingEnabled(in ComponentName admin);
+    ParceledListSlice retrieveSecurityLogs(in ComponentName admin);
+    ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin);
 
     boolean isUninstallInQueue(String packageName);
     void uninstallPackageWithActiveAdmins(String packageName);
diff --git a/core/java/android/auditing/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
similarity index 98%
rename from core/java/android/auditing/SecurityLog.java
rename to core/java/android/app/admin/SecurityLog.java
index 13823a2..001a81d 100644
--- a/core/java/android/auditing/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.auditing;
+package android.app.admin;
 
 import android.annotation.IntDef;
 import android.os.Parcel;
@@ -92,7 +92,7 @@
     public static final int TAG_KEYGUARD_SECURED = SecurityLogTags.SECURITY_KEYGUARD_SECURED;
 
     /**
-     * Returns if device logging is enabled. Log producers should only write new logs if this is
+     * Returns if security logging is enabled. Log producers should only write new logs if this is
      * true. Under the hood this is the logical AND of whether device owner exists and whether
      * it enables logging by setting the system property {@link #PROPERTY_LOGGING_ENABLED}.
      * @hide
diff --git a/core/java/android/auditing/SecurityLogTags.logtags b/core/java/android/app/admin/SecurityLogTags.logtags
similarity index 93%
rename from core/java/android/auditing/SecurityLogTags.logtags
rename to core/java/android/app/admin/SecurityLogTags.logtags
index ccc3799..39371c7 100644
--- a/core/java/android/auditing/SecurityLogTags.logtags
+++ b/core/java/android/app/admin/SecurityLogTags.logtags
@@ -1,6 +1,6 @@
 # See system/core/logcat/event.logtags for a description of the format of this file.
 
-option java_package android.auditing
+option java_package android.app.admin
 
 210001 security_adb_shell_interactive
 210002 security_adb_shell_command               (command|3)
diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java
index 30c11ef..f256a95 100644
--- a/core/java/android/app/backup/WallpaperBackupHelper.java
+++ b/core/java/android/app/backup/WallpaperBackupHelper.java
@@ -120,6 +120,7 @@
      * need to be backed up, write them to the data stream, and fill in newState with the
      * state as it exists now.
      */
+    @Override
     public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
             ParcelFileDescriptor newState) {
         performBackup_checked(oldState, data, newState, mFiles, mKeys);
@@ -130,6 +131,7 @@
      * magic wallpaper file, take specific action to determine whether it is suitable for
      * the current device.
      */
+    @Override
     public void restoreEntity(BackupDataInputStream data) {
         final String key = data.getKey();
         if (isKeyInList(key, mKeys)) {
@@ -174,12 +176,8 @@
                     }
 
                     // We passed the acceptable-dimensions test (if any), so we're going to
-                    // use the restored image.
-                    // TODO: spin a service to copy the restored image to sd/usb storage,
-                    // since it does not exist anywhere other than the private wallpaper
-                    // file.
-                    Slog.d(TAG, "Applying restored wallpaper image.");
-                    f.renameTo(new File(WALLPAPER_IMAGE));
+                    // use the restored image.  That comes last, when we are done restoring
+                    // both the pixels and the metadata.
                 }
             } else if (key.equals(WALLPAPER_INFO_KEY)) {
                 // XML file containing wallpaper info
@@ -188,4 +186,20 @@
             }
         }
     }
+
+    /**
+     * Hook for the agent to call this helper upon completion of the restore.  We do this
+     * upon completion so that we know both the imagery and the wallpaper info have
+     * been emplaced without requiring either or relying on ordering.
+     */
+    public void onRestoreFinished() {
+        final File f = new File(STAGE_FILE);
+        if (f.exists()) {
+            // TODO: spin a service to copy the restored image to sd/usb storage,
+            // since it does not exist anywhere other than the private wallpaper
+            // file.
+            Slog.d(TAG, "Applying restored wallpaper image.");
+            f.renameTo(new File(WALLPAPER_IMAGE));
+        }
+    }
 }
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 039c9d7c..bbfec41 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -536,6 +536,9 @@
          * {@link #setPeriodic(long)} or {@link #setPersisted(boolean)}.  To continually monitor
          * for content changes, you need to schedule a new JobInfo observing the same URIs
          * before you finish execution of the JobService handling the most recent changes.</p>
+         * <p>Because because setting this property is not compatible with periodic or
+         * persisted jobs, doing so will throw an {@link java.lang.IllegalArgumentException} when
+         * {@link android.app.job.JobInfo.Builder#build()} is called.</p>
          * @param uri The content: URI to monitor.
          */
         public Builder addTriggerContentUri(@NonNull TriggerContentUri uri) {
diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java
index 9f1a9cf0..6d5c81b 100644
--- a/core/java/android/app/usage/NetworkStats.java
+++ b/core/java/android/app/usage/NetworkStats.java
@@ -16,6 +16,7 @@
 
 package android.app.usage;
 
+import android.annotation.IntDef;
 import android.content.Context;
 import android.net.INetworkStatsService;
 import android.net.INetworkStatsSession;
@@ -29,6 +30,9 @@
 
 import dalvik.system.CloseGuard;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Class providing enumeration over buckets of network usage statistics. {@link NetworkStats} objects
  * are returned as results to various queries in {@link NetworkStatsManager}.
@@ -119,6 +123,11 @@
      * aggregated (e.g. time or state) some values may be equal across all buckets.
      */
     public static class Bucket {
+        /** @hide */
+        @IntDef({STATE_ALL, STATE_DEFAULT, STATE_FOREGROUND})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface State {}
+
         /**
          * Combined usage across all states.
          */
@@ -149,20 +158,34 @@
          */
         public static final int UID_TETHERING = TrafficStats.UID_TETHERING;
 
+        /** @hide */
+        @IntDef({ROAMING_ALL, ROAMING_NO, ROAMING_YES})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface Roaming {}
+
         /**
-         * Combined usage across all roaming states.
+         * Combined usage across all roaming states. Covers both roaming and non-roaming usage.
          */
         public static final int ROAMING_ALL = -1;
 
         /**
-         * Usage not accounted for in any other roaming state.
+         * Usage that occurs on a home, non-roaming network.
+         *
+         * <p>Any cellular usage in this bucket was incurred while the device was connected to a
+         * tower owned or operated by the user's wireless carrier, or a tower that the user's
+         * wireless carrier has indicated should be treated as a home network regardless.
+         *
+         * <p>This is also the default value for network types that do not support roaming.
          */
-        public static final int ROAMING_DEFAULT = 0x1;
+        public static final int ROAMING_NO = 0x1;
 
         /**
-         * Roaming usage.
+         * Usage that occurs on a roaming network.
+         *
+         * <p>Any cellular usage in this bucket as incurred while the device was roaming on another
+         * carrier's network, for which additional charges may apply.
          */
-        public static final int ROAMING_ROAMING = 0x2;
+        public static final int ROAMING_YES = 0x2;
 
         /**
          * Special TAG value matching any tag.
@@ -185,7 +208,7 @@
         private long mTxBytes;
         private long mTxPackets;
 
-        private static int convertState(int networkStatsSet) {
+        private static @State int convertState(int networkStatsSet) {
             switch (networkStatsSet) {
                 case android.net.NetworkStats.SET_ALL : return STATE_ALL;
                 case android.net.NetworkStats.SET_DEFAULT : return STATE_DEFAULT;
@@ -210,11 +233,11 @@
             return tag;
         }
 
-        private static int convertRoaming(int roaming) {
+        private static @Roaming int convertRoaming(int roaming) {
             switch (roaming) {
                 case android.net.NetworkStats.ROAMING_ALL : return ROAMING_ALL;
-                case android.net.NetworkStats.ROAMING_DEFAULT : return ROAMING_DEFAULT;
-                case android.net.NetworkStats.ROAMING_ROAMING : return ROAMING_ROAMING;
+                case android.net.NetworkStats.ROAMING_NO: return ROAMING_NO;
+                case android.net.NetworkStats.ROAMING_YES: return ROAMING_YES;
             }
             return 0;
         }
@@ -252,7 +275,7 @@
          * </ul>
          * @return Usage state.
          */
-        public int getState() {
+        public @State int getState() {
             return mState;
         }
 
@@ -260,11 +283,11 @@
          * Roaming state. One of the following values:<p/>
          * <ul>
          * <li>{@link #ROAMING_ALL}</li>
-         * <li>{@link #ROAMING_DEFAULT}</li>
-         * <li>{@link #ROAMING_ROAMING}</li>
+         * <li>{@link #ROAMING_NO}</li>
+         * <li>{@link #ROAMING_YES}</li>
          * </ul>
          */
-        public int getRoaming() {
+        public @Roaming int getRoaming() {
             return mRoaming;
         }
 
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index eb4cb91..d762a17 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2015 The Android Open Source Project
+ * Copyright (C) 2009-2016 The Android Open Source Project
  * Copyright (C) 2015 Samsung LSI
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -1837,6 +1837,9 @@
         } else if (profile == BluetoothProfile.SAP) {
             BluetoothSap sap = new BluetoothSap(context, listener);
             return true;
+        } else if (profile == BluetoothProfile.PBAP_CLIENT) {
+            BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
+            return true;
         } else {
             return false;
         }
@@ -1905,6 +1908,10 @@
                 BluetoothSap sap = (BluetoothSap)proxy;
                 sap.close();
                 break;
+            case BluetoothProfile.PBAP_CLIENT:
+                BluetoothPbapClient pbapClient = (BluetoothPbapClient)proxy;
+                pbapClient.close();
+                break;
         }
     }
 
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
new file mode 100644
index 0000000..736e55d
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothPbapClient.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2016 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.bluetooth;
+
+import java.util.List;
+import java.util.ArrayList;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.RemoteException;
+import android.os.IBinder;
+import android.util.Log;
+
+/**
+ * This class provides the APIs to control the Bluetooth PBAP Client Profile.
+ *@hide
+ */
+public final class BluetoothPbapClient implements BluetoothProfile {
+
+    private static final String TAG = "BluetoothPbapClient";
+    private static final boolean DBG = false;
+    private static final boolean VDBG = false;
+
+    public static final String ACTION_CONNECTION_STATE_CHANGED =
+        "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
+
+    private IBluetoothPbapClient mService;
+    private BluetoothDevice mDevice;
+    private final Context mContext;
+    private ServiceListener mServiceListener;
+    private BluetoothAdapter mAdapter;
+
+    /** There was an error trying to obtain the state */
+    public static final int STATE_ERROR        = -1;
+
+    public static final int RESULT_FAILURE = 0;
+    public static final int RESULT_SUCCESS = 1;
+    /** Connection canceled before completion. */
+    public static final int RESULT_CANCELED = 2;
+
+    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+            new IBluetoothStateChangeCallback.Stub() {
+                public void onBluetoothStateChange(boolean up) {
+                    if (DBG) {
+                        Log.d(TAG, "onBluetoothStateChange: PBAP CLIENT up=" + up);
+                    }
+                    if (!up) {
+                        if (VDBG) {
+                            Log.d(TAG,"Unbinding service...");
+                        }
+                        synchronized (mConnection) {
+                            try {
+                                mService = null;
+                                mContext.unbindService(mConnection);
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    } else {
+                        synchronized (mConnection) {
+                            try {
+                                if (mService == null) {
+                                    if (VDBG) {
+                                        Log.d(TAG,"Binding service...");
+                                    }
+                                    doBind();
+                                }
+                            } catch (Exception re) {
+                                Log.e(TAG,"",re);
+                            }
+                        }
+                    }
+                }
+        };
+
+    /**
+     * Create a BluetoothPbapClient proxy object.
+     */
+    BluetoothPbapClient(Context context, ServiceListener l) {
+        if (DBG) {
+            Log.d(TAG, "Create BluetoothPbapClient proxy object");
+        }
+        mContext = context;
+        mServiceListener = l;
+        mAdapter = BluetoothAdapter.getDefaultAdapter();
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG,"",e);
+            }
+        }
+        doBind();
+    }
+
+    private boolean doBind() {
+        Intent intent = new Intent(IBluetoothPbapClient.class.getName());
+        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
+        intent.setComponent(comp);
+        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
+                android.os.Process.myUserHandle())) {
+            Log.e(TAG, "Could not bind to Bluetooth PBAP Client Service with " + intent);
+            return false;
+        }
+        return true;
+    }
+
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Close the connection to the backing service.
+     * Other public functions of BluetoothPbapClient will return default error
+     * results once close() has been called. Multiple invocations of close()
+     * are ok.
+     */
+    public synchronized void close() {
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (Exception e) {
+                Log.e(TAG,"",e);
+            }
+        }
+
+        synchronized (mConnection) {
+            if (mService != null) {
+                try {
+                    mService = null;
+                    mContext.unbindService(mConnection);
+                } catch (Exception re) {
+                    Log.e(TAG,"",re);
+                }
+            }
+        }
+        mServiceListener = null;
+    }
+
+    /**
+     * Initiate connection.
+     * Upon successful connection to remote PBAP server the Client will
+     * attempt to automatically download the users phonebook and call log.
+     *
+     * @param device    a remote device we want connect to
+     * @return <code>true</code> if command has been issued successfully;
+     *         <code>false</code> otherwise;
+     */
+    public boolean connect(BluetoothDevice device) {
+        if (DBG) {
+            log("connect(" + device + ") for PBAP Client.");
+        }
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                mDevice = device;
+                return mService.connect(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        if (mService == null) {
+            Log.w(TAG, "Proxy not attached to service");
+        }
+        return false;
+    }
+
+    /**
+     * Initiate disconnect.
+     *
+     * @param device Remote Bluetooth Device
+     * @return false on error,
+     *               true otherwise
+     */
+    public boolean disconnect() {
+        if (DBG) {
+            log("disconnect(" + mDevice + ")");
+        }
+        if (mService != null && isEnabled() && isValidDevice(mDevice)) {
+            try {
+                mService.disconnect(mDevice);
+                return true;
+            } catch (RemoteException e) {
+              Log.e(TAG, Log.getStackTraceString(new Throwable()));
+              return false;
+            }
+        }
+        if (mService == null) {
+            Log.w(TAG, "Proxy not attached to service");
+        }
+        return false;
+    }
+
+    /**
+     * Get the list of connected devices.
+     * Currently at most one.
+     *
+     * @return list of connected devices
+     */
+    @Override
+    public List<BluetoothDevice> getConnectedDevices() {
+        if (DBG) {
+            log("getConnectedDevices()");
+        }
+        if (mService != null && isEnabled()) {
+            try {
+                return mService.getConnectedDevices();
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+                return new ArrayList<BluetoothDevice>();
+            }
+        }
+        if (mService == null) {
+            Log.w(TAG, "Proxy not attached to service");
+        }
+        return new ArrayList<BluetoothDevice>();
+    }
+
+    /**
+     * Get the list of devices matching specified states. Currently at most one.
+     *
+     * @return list of matching devices
+     */
+    @Override
+    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+        if (DBG) {
+            log("getDevicesMatchingStates()");
+        }
+        if (mService != null && isEnabled()) {
+            try {
+                return mService.getDevicesMatchingConnectionStates(states);
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+                return new ArrayList<BluetoothDevice>();
+            }
+        }
+        if (mService == null) {
+            Log.w(TAG, "Proxy not attached to service");
+        }
+        return new ArrayList<BluetoothDevice>();
+    }
+
+    /**
+     * Get connection state of device
+     *
+     * @return device connection state
+     */
+    @Override
+    public int getConnectionState(BluetoothDevice device) {
+        if (DBG) {
+            log("getConnectionState(" + device + ")");
+        }
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.getConnectionState(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+                return BluetoothProfile.STATE_DISCONNECTED;
+            }
+        }
+        if (mService == null) {
+            Log.w(TAG, "Proxy not attached to service");
+        }
+        return BluetoothProfile.STATE_DISCONNECTED;
+    }
+
+    private final ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) {
+                log("Proxy object connected");
+            }
+            mService = IBluetoothPbapClient.Stub.asInterface(service);
+            if (mServiceListener != null) {
+                mServiceListener.onServiceConnected(BluetoothProfile.PBAP_CLIENT, BluetoothPbapClient.this);
+            }
+        }
+        public void onServiceDisconnected(ComponentName className) {
+            if (DBG) {
+                log("Proxy object disconnected");
+            }
+            mService = null;
+            if (mServiceListener != null) {
+                mServiceListener.onServiceDisconnected(BluetoothProfile.PBAP_CLIENT);
+            }
+        }
+    };
+
+    private static void log(String msg) {
+        Log.d(TAG, msg);
+    }
+
+    private boolean isEnabled() {
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) {
+            return true;
+        }
+        log("Bluetooth is Not enabled");
+        return false;
+    }
+
+    private boolean isValidDevice(BluetoothDevice device) {
+       if (device == null) {
+           return false;
+       }
+       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
+           return true;
+       }
+       return false;
+    }
+}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index cbce22c..eee66d1 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -131,6 +131,12 @@
     public static final int HEADSET_CLIENT = 16;
 
     /**
+     * PBAP Client
+     * @hide
+     */
+    public static final int PBAP_CLIENT = 17;
+
+    /**
      * Default priority for devices that we try to auto-connect to and
      * and allow incoming connections for the profile
      * @hide
diff --git a/core/java/android/bluetooth/IBluetoothPbapClient.aidl b/core/java/android/bluetooth/IBluetoothPbapClient.aidl
new file mode 100644
index 0000000..b26ea29
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothPbapClient.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 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.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * API for Bluetooth Phone Book Access Provile Client Side
+ *
+ * {@hide}
+ */
+interface IBluetoothPbapClient {
+    boolean connect(in BluetoothDevice device);
+    boolean disconnect(in BluetoothDevice device);
+    List<BluetoothDevice> getConnectedDevices();
+    List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+    int getConnectionState(in BluetoothDevice device);
+}
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 0ec58ea..58630b0 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -836,6 +836,17 @@
         }
     }
 
+    /** {@hide} */
+    public void prepareToEnterProcess() {
+        final int size = mItems.size();
+        for (int i = 0; i < size; i++) {
+            final Item item = mItems.get(i);
+            if (item.mIntent != null) {
+                item.mIntent.prepareToEnterProcess();
+            }
+        }
+    }
+
     /** @hide */
     public void fixUris(int contentUserHint) {
         final int size = mItems.size();
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 4e1b6e0..441f188 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -2440,6 +2440,28 @@
         }
     }
 
+    /** {@hide} */
+    public void putCache(Uri key, Bundle value) {
+        try {
+            getContentService().putCache(mContext.getPackageName(), key, value,
+                    mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** {@hide} */
+    public Bundle getCache(Uri key) {
+        try {
+            final Bundle bundle = getContentService().getCache(mContext.getPackageName(), key,
+                    mContext.getUserId());
+            if (bundle != null) bundle.setClassLoader(mContext.getClassLoader());
+            return bundle;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /**
      * Returns sampling percentage for a given duration.
      *
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index f96ddf0..c4dfdcf 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2681,6 +2681,7 @@
             HARDWARE_PROPERTIES_SERVICE,
             //@hide: SOUND_TRIGGER_SERVICE,
             SHORTCUT_SERVICE,
+            //@hide: CONTEXTHUB_SERVICE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ServiceName {}
@@ -2742,7 +2743,7 @@
      * <dt> {@link #NETWORK_STATS_SERVICE} ("netstats")
      * <dd> A {@link android.app.usage.NetworkStatsManager NetworkStatsManager} for querying network
      * usage statistics.
-     * <dt> {@link #HARDWARE_PROPERTIES_SERVICE} ("hardwareproperties")
+     * <dt> {@link #HARDWARE_PROPERTIES_SERVICE} ("hardware_properties")
      * <dd> A {@link android.os.HardwarePropertiesManager} for accessing hardware properties.
      * </dl>
      *
@@ -3574,7 +3575,7 @@
      *
      * @see #getSystemService
      */
-    public static final String HARDWARE_PROPERTIES_SERVICE = "hardwareproperties";
+    public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
 
     /**
      * TODO Javadoc
@@ -3585,6 +3586,27 @@
     public static final String SHORTCUT_SERVICE = "shortcut";
 
     /**
+     * Use with {@link #getSystemService} to retrieve a {@link
+     * android.hardware.location.ContextHubManager} for accessing context hubs.
+     *
+     * @see #getSystemService
+     * @see android.hardware.location.ContextHubManager
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String CONTEXTHUB_SERVICE = "contexthub";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
+     * {@link android.os.health.SystemHealthManager} for accessing system health (battery, power,
+     * memory, etc) metrics.
+     *
+     * @see #getSystemService
+     */
+    public static final String SYSTEM_HEALTH_SERVICE = "systemhealth";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 8b471a0..d47e780 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -179,6 +179,8 @@
             int userId);
 
     void addStatusChangeListener(int mask, ISyncStatusObserver callback);
-
     void removeStatusChangeListener(ISyncStatusObserver callback);
+
+    void putCache(in String packageName, in Uri key, in Bundle value, int userId);
+    Bundle getCache(in String packageName, in Uri key, int userId);
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 09fa5e11..09aad3b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -660,6 +660,8 @@
     /**
      * Activity Action: Quick view the data. Launches a quick viewer for
      * a URI or a list of URIs.
+     * <p>Activities handling this intent action should handle the vast majority of
+     * MIME types rather than only specific ones.
      * <p>Input: {@link #getData} is a mandatory content URI of the item to
      * preview. {@link #getClipData} contains an optional list of content URIs
      * if there is more than one item to preview. {@link #EXTRA_INDEX} is an
@@ -4142,7 +4144,8 @@
 
     /**
      * Optional index with semantics depending on the intent action.
-     * @see #ACTION_QUICK_VIEW
+     *
+     * <p>The value must be an integer greater or equal to 0.
      */
     public static final String EXTRA_INDEX = "android.intent.extra.INDEX";
 
@@ -4560,7 +4563,8 @@
     /**
      * This flag is only used in split-screen multi-window mode. The new activity will be displayed
      * adjacent to the one launching it. This can only be used in conjunction with
-     * {@link #FLAG_ACTIVITY_NEW_TASK}.
+     * {@link #FLAG_ACTIVITY_NEW_TASK}. Also, setting {@link #FLAG_ACTIVITY_MULTIPLE_TASK} is
+     * required if you want a new instance of an existing activity to be created.
      */
     public static final int FLAG_ACTIVITY_LAUNCH_ADJACENT = 0x00001000;
 
@@ -6033,13 +6037,20 @@
         return mExtras != null && mExtras.hasFileDescriptors();
     }
 
-    /** @hide */
+    /** {@hide} */
     public void setAllowFds(boolean allowFds) {
         if (mExtras != null) {
             mExtras.setAllowFds(allowFds);
         }
     }
 
+    /** {@hide} */
+    public void setDefusable(boolean defusable) {
+        if (mExtras != null) {
+            mExtras.setDefusable(defusable);
+        }
+    }
+
     /**
      * Retrieve extended data from the intent.
      *
@@ -8934,6 +8945,17 @@
      * @hide
      */
     public void prepareToEnterProcess() {
+        // We just entered destination process, so we should be able to read all
+        // parcelables inside.
+        setDefusable(true);
+
+        if (mSelector != null) {
+            mSelector.prepareToEnterProcess();
+        }
+        if (mClipData != null) {
+            mClipData.prepareToEnterProcess();
+        }
+
         if (mContentUserHint != UserHandle.USER_CURRENT) {
             if (UserHandle.getAppId(Process.myUid()) != Process.SYSTEM_UID) {
                 fixUris(mContentUserHint);
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 14ef61c..5da3c86 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.content.res.Configuration;
+import android.content.res.Configuration.NativeConfig;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Printer;
@@ -495,6 +496,28 @@
     @ScreenOrientation
     public int screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
 
+    /** @hide */
+    @IntDef(flag = true,
+            value = {
+                    CONFIG_MCC,
+                    CONFIG_MNC,
+                    CONFIG_LOCALE,
+                    CONFIG_TOUCHSCREEN,
+                    CONFIG_KEYBOARD,
+                    CONFIG_KEYBOARD_HIDDEN,
+                    CONFIG_NAVIGATION,
+                    CONFIG_ORIENTATION,
+                    CONFIG_SCREEN_LAYOUT,
+                    CONFIG_UI_MODE,
+                    CONFIG_SCREEN_SIZE,
+                    CONFIG_SMALLEST_SCREEN_SIZE,
+                    CONFIG_DENSITY,
+                    CONFIG_LAYOUT_DIRECTION,
+                    CONFIG_FONT_SCALE,
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Config {}
+
     /**
      * Bit in {@link #configChanges} that indicates that the activity
      * can itself handle changes to the IMSI MCC.  Set from the
@@ -629,7 +652,7 @@
      *
      * @hide
      */
-    public static int activityInfoConfigToNative(int input) {
+    public static @NativeConfig int activityInfoConfigJavaToNative(@Config int input) {
         int output = 0;
         for (int i = 0; i < CONFIG_NATIVE_BITS.length; i++) {
             if ((input & (1 << i)) != 0) {
@@ -644,7 +667,7 @@
      *
      * @hide
      */
-    public static int activityInfoConfigNativeToJava(int input) {
+    public static @Config int activityInfoConfigNativeToJava(@NativeConfig int input) {
         int output = 0;
         for (int i = 0; i < CONFIG_NATIVE_BITS.length; i++) {
             if ((input & CONFIG_NATIVE_BITS[i]) != 0) {
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index ad174f6..58d75f7 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -707,6 +707,12 @@
     public int uid;
     
     /**
+     * The minimum SDK version this application can run on. It will not run
+     * on earlier versions.
+     */
+    public String minSdkVersion;
+
+    /**
      * The minimum SDK version this application targets.  It may run on earlier
      * versions, but it knows how to work with any new behavior added at this
      * version.  Will be {@link android.os.Build.VERSION_CODES#CUR_DEVELOPMENT}
@@ -790,7 +796,9 @@
                 pw.println(prefix + "sharedLibraryFiles=" + Arrays.toString(sharedLibraryFiles));
             }
         }
-        pw.println(prefix + "enabled=" + enabled + " targetSdkVersion=" + targetSdkVersion
+        pw.println(prefix + "enabled=" + enabled
+                + " minSdkVersion=" + minSdkVersion
+                + " targetSdkVersion=" + targetSdkVersion
                 + " versionCode=" + versionCode);
         if ((flags&DUMP_FLAG_DETAILS) != 0) {
             if (manageSpaceActivityName != null) {
@@ -884,6 +892,7 @@
         deviceEncryptedDataDir = orig.deviceEncryptedDataDir;
         credentialEncryptedDataDir = orig.credentialEncryptedDataDir;
         uid = orig.uid;
+        minSdkVersion = orig.minSdkVersion;
         targetSdkVersion = orig.targetSdkVersion;
         versionCode = orig.versionCode;
         enabled = orig.enabled;
@@ -938,6 +947,7 @@
         dest.writeString(deviceEncryptedDataDir);
         dest.writeString(credentialEncryptedDataDir);
         dest.writeInt(uid);
+        dest.writeString(minSdkVersion);
         dest.writeInt(targetSdkVersion);
         dest.writeInt(versionCode);
         dest.writeInt(enabled ? 1 : 0);
@@ -992,6 +1002,7 @@
         deviceEncryptedDataDir = source.readString();
         credentialEncryptedDataDir = source.readString();
         uid = source.readInt();
+        minSdkVersion = source.readString();
         targetSdkVersion = source.readInt();
         versionCode = source.readInt();
         enabled = source.readInt() != 0;
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index cf3e298..6b3d4f1 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -26,13 +26,15 @@
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.os.ParcelFileDescriptor;
+
 import java.util.List;
 
 /**
  * {@hide}
  */
 interface ILauncherApps {
-    void addOnAppsChangedListener(in IOnAppsChangedListener listener);
+    void addOnAppsChangedListener(String callingPackage, in IOnAppsChangedListener listener);
     void removeOnAppsChangedListener(in IOnAppsChangedListener listener);
     ParceledListSlice getLauncherActivities(String packageName, in UserHandle user);
     ResolveInfo resolveActivity(in Intent intent, in UserHandle user);
@@ -52,4 +54,10 @@
             in UserHandle user);
     boolean startShortcut(String callingPackage, String packageName, String id,
             in Rect sourceBounds, in Bundle startActivityOptions, in UserHandle user);
+
+    int getShortcutIconResId(String callingPackage, in ShortcutInfo shortcut, in UserHandle user);
+    ParcelFileDescriptor getShortcutIconFd(String callingPackage, in ShortcutInfo shortcut,
+            in UserHandle user);
+
+    boolean hasShortcutHostPermission(String callingPackage);
 }
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index aee3ba7..2a3fac3 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -29,6 +29,8 @@
     ParcelFileDescriptor openWrite(String name, long offsetBytes, long lengthBytes);
     ParcelFileDescriptor openRead(String name);
 
+    void removeSplit(String splitName);
+
     void close();
     void commit(in IntentSender statusReceiver);
     void abandon();
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index c684447..dabc652 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -291,6 +291,8 @@
      */
      ComponentName getHomeActivities(out List<ResolveInfo> outHomeCandidates);
 
+    void setHomeActivity(in ComponentName className, int userId);
+
     /**
      * As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}.
      */
@@ -314,6 +316,11 @@
     int getApplicationEnabledSetting(in String packageName, int userId);
 
     /**
+     * As per {@link android.content.pm.PackageManager#flushPackageRestrictionsAsUser}.
+     */
+    void flushPackageRestrictionsAsUser(in int userId);
+
+    /**
      * Set whether the given package should be considered stopped, making
      * it not visible to implicit intents that filter out stopped packages.
      */
@@ -535,5 +542,4 @@
     boolean isPackageDeviceAdminOnAnyUser(String packageName);
 
     List<String> getPreviousCodePaths(in String packageName);
-
 }
diff --git a/core/java/android/content/pm/IShortcutService.aidl b/core/java/android/content/pm/IShortcutService.aidl
index 23e671d..8f9dcfc 100644
--- a/core/java/android/content/pm/IShortcutService.aidl
+++ b/core/java/android/content/pm/IShortcutService.aidl
@@ -44,5 +44,7 @@
 
     long getRateLimitResetTime(String packageName, int userId);
 
+    int getIconMaxDimensions(String packageName, int userId);
+
     void resetThrottling(); // system only API for developer opsions
 }
\ No newline at end of file
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 8e4a0e2..8724d5e 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -16,11 +16,9 @@
 
 package android.content.pm;
 
-import android.Manifest.permission;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -30,7 +28,6 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -159,6 +156,9 @@
          * Indicates that one or more shortcuts (which may be dynamic and/or pinned)
          * have been added, updated or removed.
          *
+         * <p>Only the applications that are allowed to access the shortcut information,
+         * as defined in {@link #hasShortcutHostPermission()}, will receive it.
+         *
          * @param packageName The name of the package that has the shortcuts.
          * @param shortcuts all shortcuts from the package (dynamic and/or pinned).
          * @param user The UserHandle of the profile that generated the change.
@@ -183,7 +183,8 @@
         public static final int FLAG_GET_PINNED = 1 << 1;
 
         /**
-         * Requests "key" fields only.
+         * Requests "key" fields only.  See {@link ShortcutInfo#hasKeyFieldsOnly()} for which
+         * fields are available.
          */
         public static final int FLAG_GET_KEY_FIELDS_ONLY = 1 << 2;
 
@@ -394,16 +395,34 @@
     }
 
     /**
+     * Returns whether the caller can access the shortcut information.
+     *
+     * <p>Only the default launcher can access the shortcut information.
+     *
+     * <p>Note when this method returns {@code false}, that may be a temporary situation because
+     * the user is trying a new launcher application.  The user may decide to change the default
+     * launcher to the calling application again, so even if a launcher application loses
+     * this permission, it does <b>not</b> have to purge pinned shortcut information.
+     */
+    public boolean hasShortcutHostPermission() {
+        try {
+            return mService.hasShortcutHostPermission(mContext.getPackageName());
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns the IDs of {@link ShortcutInfo}s that match {@code query}.
      *
-     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
      *
      * @param query result includes shortcuts matching this query.
      * @param user The UserHandle of the profile.
      *
      * @return the IDs of {@link ShortcutInfo}s that match the query.
      */
-    @RequiresPermission(permission.BIND_APPWIDGET)
     @Nullable
     public List<ShortcutInfo> getShortcuts(@NonNull ShortcutQuery query,
             @NonNull UserHandle user) {
@@ -419,7 +438,8 @@
     /**
      * Returns {@link ShortcutInfo}s with the given IDs from a package.
      *
-     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
      *
      * @param packageName The target package.
      * @param ids IDs of the shortcuts to retrieve.
@@ -427,7 +447,6 @@
      *
      * @return list of {@link ShortcutInfo} associated with the package.
      */
-    @RequiresPermission(permission.BIND_APPWIDGET)
     @Nullable
     public List<ShortcutInfo> getShortcutInfo(@NonNull String packageName,
             @NonNull List<String> ids, @NonNull UserHandle user) {
@@ -446,13 +465,13 @@
      * <p>This API is <b>NOT</b> cumulative; this will replace all pinned shortcuts for the package.
      * However, different launchers may have different set of pinned shortcuts.
      *
-     * <p>Callers must have the {@link permission#BIND_APPWIDGET} permission.
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
      *
      * @param packageName The target package name.
      * @param shortcutIds The IDs of the shortcut to be pinned.
      * @param user The UserHandle of the profile.
      */
-    @RequiresPermission(permission.BIND_APPWIDGET)
     public void pinShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds,
             @NonNull UserHandle user) {
         try {
@@ -466,35 +485,44 @@
      * Return the icon resource ID, if {@code shortcut} has one
      * (i.e. when {@link ShortcutInfo#hasIconResource()} returns {@code true}).
      *
-     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
      *
      * @param shortcut The target shortcut.
      * @param user The UserHandle of the profile.
      */
-    @RequiresPermission(permission.BIND_APPWIDGET)
     public int getShortcutIconResId(@NonNull ShortcutInfo shortcut, @NonNull UserHandle user) {
-        throw new RuntimeException("not implemented yet");
+        try {
+            return mService.getShortcutIconResId(mContext.getPackageName(), shortcut, user);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
      * Return the icon as {@link ParcelFileDescriptor}, when it's stored as a file
      * (i.e. when {@link ShortcutInfo#hasIconFile()} returns {@code true}).
      *
-     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
      *
      * @param shortcut The target shortcut.
      * @param user The UserHandle of the profile.
      */
-    @RequiresPermission(permission.BIND_APPWIDGET)
     public ParcelFileDescriptor getShortcutIconFd(
             @NonNull ShortcutInfo shortcut, @NonNull UserHandle user) {
-        throw new RuntimeException("not implemented yet");
+        try {
+            return mService.getShortcutIconFd(mContext.getPackageName(), shortcut, user);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
      * Launches a shortcut.
      *
-     * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission.
+     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+     * #hasShortcutHostPermission()}.
      *
      * @param packageName The target shortcut package name.
      * @param shortcutId The target shortcut ID.
@@ -504,7 +532,6 @@
      * @return {@code false} when the shortcut is no longer valid (e.g. the creator application
      *   has been uninstalled). {@code true} when the shortcut is still valid.
      */
-    @RequiresPermission(permission.BIND_APPWIDGET)
     public boolean startShortcut(@NonNull String packageName, @NonNull String shortcutId,
             @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
             @NonNull UserHandle user) {
@@ -538,7 +565,8 @@
                 addCallbackLocked(callback, handler);
                 if (addedFirstCallback) {
                     try {
-                        mService.addOnAppsChangedListener(mAppsChangedListener);
+                        mService.addOnAppsChangedListener(mContext.getPackageName(),
+                                mAppsChangedListener);
                     } catch (RemoteException re) {
                         throw re.rethrowFromSystemServer();
                     }
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 700a40d..56dcdb7 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -37,7 +37,6 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.util.ExceptionUtils;
-import android.util.Log;
 
 import com.android.internal.util.IndentingPrintWriter;
 
@@ -47,7 +46,6 @@
 import java.io.OutputStream;
 import java.security.MessageDigest;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
@@ -393,13 +391,6 @@
      * Return list of all known install sessions, regardless of the installer.
      */
     public @NonNull List<SessionInfo> getAllSessions() {
-        final ApplicationInfo info = mContext.getApplicationInfo();
-        if ("com.google.android.googlequicksearchbox".equals(info.packageName)
-                && info.versionCode <= 300400110) {
-            Log.d(TAG, "Ignoring callback request from old prebuilt");
-            return Collections.EMPTY_LIST;
-        }
-
         try {
             return mInstaller.getAllSessions(mUserId).getList();
         } catch (RemoteException e) {
@@ -597,14 +588,6 @@
      *            calling thread.
      */
     public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
-        // TODO: remove this temporary guard once we have new prebuilts
-        final ApplicationInfo info = mContext.getApplicationInfo();
-        if ("com.google.android.googlequicksearchbox".equals(info.packageName)
-                && info.versionCode <= 300400110) {
-            Log.d(TAG, "Ignoring callback request from old prebuilt");
-            return;
-        }
-
         synchronized (mDelegates) {
             final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
                     handler.getLooper());
@@ -795,6 +778,27 @@
         }
 
         /**
+         * Removes a split.
+         * <p>
+         * Split removals occur prior to adding new APKs. If upgrading a feature
+         * split, it is not expected nor desirable to remove the split prior to
+         * upgrading.
+         * <p>
+         * When split removal is bundled with new APKs, the packageName must be
+         * identical.
+         */
+        public void removeSplit(@NonNull String splitName) throws IOException {
+            try {
+                mSession.removeSplit(splitName);
+            } catch (RuntimeException e) {
+                ExceptionUtils.maybeUnwrapIOException(e);
+                throw e;
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
          * Attempt to commit everything staged in this session. This may require
          * user intervention, and so it may not happen immediately. The final
          * result of the commit will be reported through the given callback.
@@ -979,8 +983,8 @@
         }
 
         /**
-         * Optionally set the URI where this package was downloaded from. Used for
-         * verification purposes.
+         * Optionally set the URI where this package was downloaded from. This is
+         * informational and may be used as a signal for anti-malware purposes.
          *
          * @see Intent#EXTRA_ORIGINATING_URI
          */
@@ -989,7 +993,8 @@
         }
 
         /**
-         * Sets the UID that initiated package installation. Used for verification purposes.
+         * Sets the UID that initiated package installation. This is informational
+         * and may be used as a signal for anti-malware purposes.
          *
          * @see PackageManager#EXTRA_VERIFICATION_INSTALLER_UID
          */
@@ -998,8 +1003,8 @@
         }
 
         /**
-         * Optionally set the URI that referred you to install this package. Used
-         * for verification purposes.
+         * Optionally set the URI that referred you to install this package. This is
+         * informational and may be used as a signal for anti-malware purposes.
          *
          * @see Intent#EXTRA_REFERRER
          */
@@ -1031,6 +1036,16 @@
         }
 
         /** {@hide} */
+        @SystemApi
+        public void setAllowDowngrade(boolean allowDowngrade) {
+            if (allowDowngrade) {
+                installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
+            } else {
+                installFlags &= ~PackageManager.INSTALL_ALLOW_DOWNGRADE;
+            }
+        }
+
+        /** {@hide} */
         public void setInstallFlagsExternal() {
             installFlags |= PackageManager.INSTALL_EXTERNAL;
             installFlags &= ~PackageManager.INSTALL_INTERNAL;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 0dc856c..c179596 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1596,9 +1596,9 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
-     * {@link #hasSystemFeature}: If this feature is supported, the Vulkan native API will enumerate
-     * at least one {@code VkPhysicalDevice}, and the feature version will indicate what
-     * level of optional hardware features limits it supports.
+     * {@link #hasSystemFeature(String, int)}: If this feature is supported, the Vulkan native API
+     * will enumerate at least one {@code VkPhysicalDevice}, and the feature version will indicate
+     * what level of optional hardware features limits it supports.
      * <p>
      * Level 0 includes the base Vulkan requirements as well as:
      * <ul><li>{@code VkPhysicalDeviceFeatures::textureCompressionETC2}</li></ul>
@@ -1623,7 +1623,7 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
-     * {@link #hasSystemFeature}: The version of this feature indicates the highest
+     * {@link #hasSystemFeature(String, int)}: The version of this feature indicates the highest
      * {@code VkPhysicalDeviceProperties::apiVersion} supported by the physical devices that support
      * the hardware level indicated by {@link #FEATURE_VULKAN_HARDWARE_LEVEL}. The feature version
      * uses the same encoding as Vulkan version numbers:
@@ -4387,10 +4387,8 @@
         int badgeDensity);
 
     /**
-     * If the target user is a managed profile of the calling user or if the
-     * target user is the caller and is itself a managed profile, then this
-     * returns a badged copy of the given icon to be able to distinguish it from
-     * the original icon. For badging an arbitrary drawable use
+     * If the target user is a managed profile, then this returns a badged copy of the given icon
+     * to be able to distinguish it from the original icon. For badging an arbitrary drawable use
      * {@link #getUserBadgedDrawableForDensity(
      * android.graphics.drawable.Drawable, UserHandle, android.graphics.Rect, int)}.
      * <p>
@@ -5227,7 +5225,6 @@
     public abstract void setComponentEnabledSetting(ComponentName componentName,
             int newState, int flags);
 
-
     /**
      * Return the enabled setting for a package component (activity,
      * receiver, service, provider).  This returns the last value set by
@@ -5285,6 +5282,16 @@
     public abstract int getApplicationEnabledSetting(String packageName);
 
     /**
+     * Flush the package restrictions for a given user to disk. This forces the package restrictions
+     * like component and package enabled settings to be written to disk and avoids the delay that
+     * is otherwise present when changing those settings.
+     *
+     * @param userId Ther userId of the user whose restrictions are to be flushed.
+     * @hide
+     */
+    public abstract void flushPackageRestrictionsAsUser(int userId);
+
+    /**
      * Puts the package in a hidden state, which is almost like an uninstalled state,
      * making the package unavailable, but it doesn't remove the data or the actual
      * package file. Application can be unhidden by either resetting the hidden state
@@ -5367,6 +5374,9 @@
      * will be hidden, the application will not show up in recents, will not be able to show
      * toasts or dialogs or ring the device.
      *
+     * <p>The package must already be installed. If the package is uninstalled while suspended
+     * the package will no longer be suspended.
+     *
      * @param packageNames The names of the packages to set the suspended status.
      * @param suspended If set to {@code true} than the packages will be suspended, if set to
      * {@code false} the packages will be unsuspended.
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 89f2fc4..13ebb82 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -16,6 +16,7 @@
 
 package android.content.pm;
 
+import android.content.ComponentName;
 import android.content.pm.PackageManager.NameNotFoundException;
 
 import java.util.List;
@@ -140,4 +141,10 @@
      *             found on the system.
      */
     public abstract ApplicationInfo getApplicationInfo(String packageName, int userId);
+
+    /**
+     * Interface to {@link com.android.server.pm.PackageManagerService#getHomeActivitiesAsUser}.
+     */
+    public abstract ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
+            int userId);
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index bc28ff1..7d7be9a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1524,6 +1524,7 @@
         childPkg.baseRevisionCode = parentPkg.baseRevisionCode;
         childPkg.mVersionName = parentPkg.mVersionName;
         childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion;
+        childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion;
 
         childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError);
         if (childPkg == null) {
@@ -1854,10 +1855,16 @@
                             com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
                     if (val != null) {
                         if (val.type == TypedValue.TYPE_STRING && val.string != null) {
-                            targetCode = minCode = val.string.toString();
+                            targetCode = val.string.toString();
+                            if (minCode == null) {
+                                minCode = targetCode;
+                            }
                         } else {
                             // If it's not a string, it's an integer.
                             targetVers = val.data;
+                            if (minVers == 0) {
+                                minVers = targetVers;
+                            }
                         }
                     }
 
@@ -1883,11 +1890,14 @@
                             mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
                             return null;
                         }
+                        pkg.applicationInfo.minSdkVersion = minCode;
                     } else if (minVers > SDK_VERSION) {
                         outError[0] = "Requires newer sdk version #" + minVers
                                 + " (current version is #" + SDK_VERSION + ")";
                         mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
                         return null;
+                    } else {
+                        pkg.applicationInfo.minSdkVersion = Integer.toString(minVers);
                     }
 
                     if (targetCode != null) {
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 6520563..e41136c 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -19,9 +19,11 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Icon;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PersistableBundle;
@@ -60,6 +62,9 @@
     /* @hide */
     public static final int FLAG_HAS_ICON_FILE = 1 << 3;
 
+    /* @hide */
+    public static final int FLAG_KEY_FIELDS_ONLY = 1 << 4;
+
     /** @hide */
     @IntDef(flag = true,
             value = {
@@ -67,6 +72,7 @@
             FLAG_PINNED,
             FLAG_HAS_ICON_RES,
             FLAG_HAS_ICON_FILE,
+            FLAG_KEY_FIELDS_ONLY,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ShortcutFlags {}
@@ -114,10 +120,15 @@
     @NonNull
     private String mTitle;
 
+    /**
+     * Intent *with extras removed*.
+     */
     @NonNull
     private Intent mIntent;
 
-    // Internal use only.
+    /**
+     * Extras for the intent.
+     */
     @NonNull
     private PersistableBundle mIntentPersistableExtras;
 
@@ -149,6 +160,13 @@
         mIcon = b.mIcon;
         mTitle = b.mTitle;
         mIntent = b.mIntent;
+        if (mIntent != null) {
+            final Bundle intentExtras = mIntent.getExtras();
+            if (intentExtras != null) {
+                mIntent.replaceExtras((Bundle) null);
+                mIntentPersistableExtras = new PersistableBundle(intentExtras);
+            }
+        }
         mWeight = b.mWeight;
         mExtras = b.mExtras;
         updateTimestamp();
@@ -170,13 +188,15 @@
     private ShortcutInfo(ShortcutInfo source, @CloneFlags int cloneFlags) {
         mId = source.mId;
         mPackageName = source.mPackageName;
-        mActivityComponent = source.mActivityComponent;
         mFlags = source.mFlags;
         mLastChangedTimestamp = source.mLastChangedTimestamp;
 
         if ((cloneFlags & CLONE_REMOVE_NON_KEY_INFO) == 0) {
+            mActivityComponent = source.mActivityComponent;
+
             if ((cloneFlags & CLONE_REMOVE_ICON) == 0) {
                 mIcon = source.mIcon;
+                mBitmapPath = source.mBitmapPath;
             }
 
             mTitle = source.mTitle;
@@ -187,7 +207,9 @@
             mWeight = source.mWeight;
             mExtras = source.mExtras;
             mIconResourceId = source.mIconResourceId;
-            mBitmapPath = source.mBitmapPath;
+        } else {
+            // Set this bit.
+            mFlags |= FLAG_KEY_FIELDS_ONLY;
         }
     }
 
@@ -210,9 +232,9 @@
      * @hide
      */
     public void copyNonNullFieldsFrom(ShortcutInfo source) {
-        Preconditions.checkState(mId == source.mId, "ID must match");
+        Preconditions.checkState(mId.equals(source.mId), "ID must match");
         Preconditions.checkState(mPackageName.equals(source.mPackageName),
-                "Package namae must match");
+                "Package name must match");
 
         if (source.mActivityComponent != null) {
             mActivityComponent = source.mActivityComponent;
@@ -239,6 +261,39 @@
     }
 
     /**
+     * @hide
+     */
+    public static Icon validateIcon(Icon icon) {
+        switch (icon.getType()) {
+            case Icon.TYPE_RESOURCE:
+            case Icon.TYPE_BITMAP:
+                break; // OK
+            case Icon.TYPE_URI:
+                if (ContentResolver.SCHEME_CONTENT.equals(icon.getUri().getScheme())) {
+                    break;
+                }
+                // Note "file:" is not supported, because depending on the path, system server
+                // cannot access it. // TODO Revisit "file:" icon support
+
+                // fall through
+            default:
+                throw getInvalidIconException();
+        }
+        if (icon.hasTint()) {
+            // TODO support it
+            throw new IllegalArgumentException("Icons with tints are not supported");
+        }
+
+        return icon;
+    }
+
+    /** @hide */
+    public static IllegalArgumentException getInvalidIconException() {
+        return new IllegalArgumentException("Unsupported icon type:"
+                +" only bitmap, resource and content URI are supported");
+    }
+
+    /**
      * Builder class for {@link ShortcutInfo} objects.
      */
     public static class Builder {
@@ -273,7 +328,9 @@
         }
 
         /**
-         * Optionally sets the target activity.
+         * Optionally sets the target activity.  If it's not set, and if the caller application
+         * has multiple launcher icons, this shortcut will be shown on all those icons.
+         * If it's set, this shortcut will be only shown on this activity.
          */
         @NonNull
         public Builder setActivityComponent(@NonNull ComponentName activityComponent) {
@@ -284,15 +341,22 @@
         /**
          * Optionally sets an icon.
          *
-         * - Tint is not supported TODO Either check and throw, or support it.
-         * - URI icons will be converted into Bitmap icons at the registration time.
+         * <ul>
+         *     <li>Tints are not supported.
+         *     <li>Bitmaps, resources and "content:" URIs are supported.
+         *     <li>"content:" URI will be fetched when a shortcut is registered to
+         *         {@link ShortcutManager}.  Changing the content from the same URI later will
+         *         not be reflected to launcher icons.
+         * </ul>
          *
-         * TODO Only allow Bitmap, Resource and URI types.  byte[] type can easily go over
-         * binder size limit.
+         * <p>For performance reasons, icons will <b>NOT</b> be available on instances
+         * returned by {@link ShortcutManager} or {@link LauncherApps}.  Launcher applications
+         * need to use {@link LauncherApps#getShortcutIconFd(ShortcutInfo, UserHandle)}
+         * and {@link LauncherApps#getShortcutIconResId(ShortcutInfo, UserHandle)}.
          */
         @NonNull
         public Builder setIcon(Icon icon) {
-            mIcon = icon;
+            mIcon = validateIcon(icon);
             return this;
         }
 
@@ -316,7 +380,7 @@
         }
 
         /**
-         * Optionally sets the weight of a shortcut, which will be used by Launcher for sorting.
+         * Optionally sets the weight of a shortcut, which will be used by the launcher for sorting.
          * The larger the weight, the more "important" a shortcut is.
          */
         @NonNull
@@ -326,8 +390,8 @@
         }
 
         /**
-         * Optional values that application can set.
-         * TODO: reserve keys starting with "android."
+         * Optional values that applications can set.  Applications can store any meta-data of
+         * shortcuts in this, and retrieve later from {@link ShortcutInfo#getExtras()}.
          */
         @NonNull
         public Builder setExtras(@NonNull PersistableBundle extras) {
@@ -353,7 +417,7 @@
     }
 
     /**
-     * Return the ID of the shortcut.
+     * Return the package name of the creator application.
      */
     @NonNull
     public String getPackageName() {
@@ -374,7 +438,7 @@
      *
      * For performance reasons, this will <b>NOT</b> be available when an instance is returned
      * by {@link ShortcutManager} or {@link LauncherApps}.  A launcher application needs to use
-     * other APIs in LauncherApps to fetch the bitmap.  TODO Add a precondition for it.
+     * other APIs in LauncherApps to fetch the bitmap.
      *
      * @hide
      */
@@ -385,22 +449,46 @@
 
     /**
      * Return the shortcut title.
+     *
+     * <p>All shortcuts must have a non-empty title, but this method will return null when
+     * {@link #hasKeyFieldsOnly()} is true.
      */
-    @NonNull
+    @Nullable
     public String getTitle() {
         return mTitle;
     }
 
     /**
      * Return the intent.
-     * TODO Set mIntentPersistableExtras and before returning.
+     *
+     * <p>All shortcuts must have an intent, but this method will return null when
+     * {@link #hasKeyFieldsOnly()} is true.
      */
-    @NonNull
+    @Nullable
     public Intent getIntent() {
+        if (mIntent == null) {
+            return null;
+        }
+        final Intent intent = new Intent(mIntent);
+        intent.replaceExtras(
+                mIntentPersistableExtras != null ? new Bundle(mIntentPersistableExtras) : null);
+        return intent;
+    }
+
+    /**
+     * Return "raw" intent, which is the original intent without the extras.
+     * @hide
+     */
+    @Nullable
+    public Intent getIntentNoExtras() {
         return mIntent;
     }
 
-    /** @hide */
+    /**
+     * The extras in the intent.  We convert extras into {@link PersistableBundle} so we can
+     * persist them.
+     * @hide
+     */
     @Nullable
     public PersistableBundle getIntentPersistableExtras() {
         return mIntentPersistableExtras;
@@ -483,6 +571,23 @@
         return hasFlags(FLAG_HAS_ICON_FILE);
     }
 
+    /**
+     * Return whether a shortcut only contains "key" information only or not.  If true, only the
+     * following fields are available.
+     * <ul>
+     *     <li>{@link #getId()}
+     *     <li>{@link #getPackageName()}
+     *     <li>{@link #getLastChangedTimestamp()}
+     *     <li>{@link #isDynamic()}
+     *     <li>{@link #isPinned()}
+     *     <li>{@link #hasIconResource()}
+     *     <li>{@link #hasIconFile()}
+     * </ul>
+     */
+    public boolean hasKeyFieldsOnly() {
+        return hasFlags(FLAG_KEY_FIELDS_ONLY);
+    }
+
     /** @hide */
     public void updateTimestamp() {
         mLastChangedTimestamp = System.currentTimeMillis();
@@ -495,33 +600,13 @@
     }
 
     /** @hide */
-    public void setIcon(Icon icon) {
-        mIcon = icon;
+    public void clearIcon() {
+        mIcon = null;
     }
 
     /** @hide */
-    public void setTitle(String title) {
-        mTitle = title;
-    }
-
-    /** @hide */
-    public void setIntent(Intent intent) {
-        mIntent = intent;
-    }
-
-    /** @hide */
-    public void setIntentPersistableExtras(PersistableBundle intentPersistableExtras) {
-        mIntentPersistableExtras = intentPersistableExtras;
-    }
-
-    /** @hide */
-    public void setWeight(int weight) {
-        mWeight = weight;
-    }
-
-    /** @hide */
-    public void setExtras(PersistableBundle extras) {
-        mExtras = extras;
+    public void setIconResourceId(int iconResourceId) {
+        mIconResourceId = iconResourceId;
     }
 
     /** @hide */
@@ -643,9 +728,10 @@
         sb.append(", extras=");
         sb.append(mExtras);
 
+        sb.append(", flags=");
+        sb.append(mFlags);
+
         if (includeInternalData) {
-            sb.append(", flags=");
-            sb.append(mFlags);
 
             sb.append(", iconRes=");
             sb.append(mIconResourceId);
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index 4c51d49..b247f65 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -239,6 +239,17 @@
         }
     }
 
+    /**
+     * Return the max width and height for icons, in pixels.
+     */
+    public int getIconMaxDimensions() {
+        try {
+            return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /** @hide injection point */
     @VisibleForTesting
     protected int injectMyUserId() {
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index 3d6028a..4255582 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -22,6 +22,8 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.LauncherApps.ShortcutQuery;
+import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
 
 import java.util.List;
 
@@ -34,8 +36,7 @@
  */
 public abstract class ShortcutServiceInternal {
     public interface ShortcutChangeListener {
-        void onShortcutChanged(@NonNull String packageName,
-                @NonNull List<ShortcutInfo> shortcuts, @UserIdInt int userId);
+        void onShortcutChanged(@NonNull String packageName, @UserIdInt int userId);
     }
 
     public abstract List<ShortcutInfo>
@@ -55,4 +56,12 @@
             @NonNull String packageName, @NonNull String shortcutId, int userId);
 
     public abstract void addListener(@NonNull ShortcutChangeListener listener);
+
+    public abstract int getShortcutIconResId(@NonNull String callingPackage,
+            @NonNull ShortcutInfo shortcut, int userId);
+
+    public abstract ParcelFileDescriptor getShortcutIconFd(@NonNull String callingPackage,
+            @NonNull ShortcutInfo shortcut, int userId);
+
+    public abstract boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId);
 }
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 7b0b98d..4ad86f7 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
+import android.content.res.Configuration.NativeConfig;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 import android.util.SparseArray;
@@ -796,7 +797,10 @@
     /*package*/ static final int STYLE_DATA = 1;
     /*package*/ static final int STYLE_ASSET_COOKIE = 2;
     /*package*/ static final int STYLE_RESOURCE_ID = 3;
-    /*package*/ static final int STYLE_CHANGING_CONFIGURATIONS = 4;
+
+    /* Offset within typed data array for native changingConfigurations. */
+    static final int STYLE_CHANGING_CONFIGURATIONS = 4;
+
     /*package*/ static final int STYLE_DENSITY = 5;
     /*package*/ native static final boolean applyStyle(long theme,
             int defStyleAttr, int defStyleRes, long xmlParser,
@@ -845,7 +849,7 @@
                                                                 TypedValue outValue,
                                                                 boolean resolve);
     /*package*/ native static final void dumpTheme(long theme, int priority, String tag, String prefix);
-    /*package*/ native static final int getThemeChangingConfigurations(long theme);
+    /*package*/ native static final @NativeConfig int getThemeChangingConfigurations(long theme);
 
     private native final long openXmlAssetNative(int cookie, String fileName);
 
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 9e1b312..fb5bfd3 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -19,6 +19,7 @@
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.Resources.Theme;
 import android.graphics.Color;
 
@@ -82,7 +83,7 @@
     private ColorStateListFactory mFactory;
 
     private int[][] mThemeAttrs;
-    private int mChangingConfigurations;
+    private @Config int mChangingConfigurations;
 
     private int[][] mStateSpecs;
     private int[] mColors;
@@ -251,7 +252,7 @@
         int depth;
         int type;
 
-        int changingConfigurations = 0;
+        @Config int changingConfigurations = 0;
         int defaultColor = DEFAULT_COLOR;
 
         boolean hasUnresolvedAttrs = false;
@@ -440,8 +441,8 @@
      *
      * @see android.content.pm.ActivityInfo
      */
-    public int getChangingConfigurations() {
-        return mChangingConfigurations;
+    public @Config int getChangingConfigurations() {
+        return super.getChangingConfigurations() | mChangingConfigurations;
     }
 
     private int modulateColorAlpha(int baseColor, float alphaMod) {
@@ -620,7 +621,7 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mSrc.mChangingConfigurations;
         }
 
diff --git a/core/java/android/content/res/ComplexColor.java b/core/java/android/content/res/ComplexColor.java
index d96ec62..b297764 100644
--- a/core/java/android/content/res/ComplexColor.java
+++ b/core/java/android/content/res/ComplexColor.java
@@ -25,6 +25,8 @@
  * {@link android.content.res.ColorStateList} or {@link android.content.res.GradientColor}
  */
 public abstract class ComplexColor {
+    private int mChangingConfigurations;
+
     /**
      * @return {@code true}  if this ComplexColor changes color based on state, {@code false}
      * otherwise.
@@ -52,4 +54,24 @@
      * @hide only for resource preloading
      */
     public abstract ComplexColor obtainForTheme(Theme t);
+
+    /**
+     * @hide only for resource preloading
+     */
+    final void setBaseChangingConfigurations(int changingConfigurations) {
+        mChangingConfigurations = changingConfigurations;
+    }
+
+    /**
+     * Returns a mask of the configuration parameters for which this color
+     * may change, requiring that it be re-created.
+     *
+     * @return a mask of the changing configuration parameters, as defined by
+     *         {@link android.content.pm.ActivityInfo}
+     *
+     * @see android.content.pm.ActivityInfo
+     */
+    public int getChangingConfigurations() {
+        return mChangingConfigurations;
+    }
 }
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index be4f895..9b1d462 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -22,8 +22,11 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ActivityInfo.Config;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -32,6 +35,8 @@
 import android.view.View;
 
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Locale;
 
@@ -663,6 +668,28 @@
      */
     public int seq;
 
+    /** @hide */
+    @IntDef(flag = true,
+            value = {
+                    NATIVE_CONFIG_MCC,
+                    NATIVE_CONFIG_MNC,
+                    NATIVE_CONFIG_LOCALE,
+                    NATIVE_CONFIG_TOUCHSCREEN,
+                    NATIVE_CONFIG_KEYBOARD,
+                    NATIVE_CONFIG_KEYBOARD_HIDDEN,
+                    NATIVE_CONFIG_NAVIGATION,
+                    NATIVE_CONFIG_ORIENTATION,
+                    NATIVE_CONFIG_DENSITY,
+                    NATIVE_CONFIG_SCREEN_SIZE,
+                    NATIVE_CONFIG_VERSION,
+                    NATIVE_CONFIG_SCREEN_LAYOUT,
+                    NATIVE_CONFIG_UI_MODE,
+                    NATIVE_CONFIG_SMALLEST_SCREEN_SIZE,
+                    NATIVE_CONFIG_LAYOUTDIR,
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface NativeConfig {}
+
     /** @hide Native-specific bit mask for MCC config; DO NOT USE UNLESS YOU ARE SURE. */
     public static final int NATIVE_CONFIG_MCC = 0x0001;
     /** @hide Native-specific bit mask for MNC config; DO NOT USE UNLESS YOU ARE SURE. */
@@ -917,14 +944,13 @@
     }
 
     /**
-     * Copy the fields from delta into this Configuration object, keeping
-     * track of which ones have changed.  Any undefined fields in
-     * <var>delta</var> are ignored and not copied in to the current
-     * Configuration.
-     * @return Returns a bit mask of the changed fields, as per
-     * {@link #diff}.
+     * Copies the fields from delta into this Configuration object, keeping
+     * track of which ones have changed. Any undefined fields in {@code delta}
+     * are ignored and not copied in to the current Configuration.
+     *
+     * @return a bit mask of the changed fields, as per {@link #diff}
      */
-    public int updateFrom(Configuration delta) {
+    public @Config int updateFrom(@NonNull Configuration delta) {
         int changed = 0;
         if (delta.fontScale > 0 && fontScale != delta.fontScale) {
             changed |= ActivityInfo.CONFIG_FONT_SCALE;
@@ -1171,17 +1197,19 @@
     }
 
     /**
-     * Determine if a new resource needs to be loaded from the bit set of
+     * Determines if a new resource needs to be loaded from the bit set of
      * configuration changes returned by {@link #updateFrom(Configuration)}.
      *
-     * @param configChanges The mask of changes configurations as returned by
-     * {@link #updateFrom(Configuration)}.
-     * @param interestingChanges The configuration changes that the resource
-     * can handled, as given in {@link android.util.TypedValue#changingConfigurations}.
-     *
-     * @return Return true if the resource needs to be loaded, else false.
+     * @param configChanges the mask of changes configurations as returned by
+     *                      {@link #updateFrom(Configuration)}
+     * @param interestingChanges the configuration changes that the resource
+     *                           can handle as given in
+     *                           {@link android.util.TypedValue#changingConfigurations}
+     * @return {@code true} if the resource needs to be loaded, {@code false}
+     *         otherwise
      */
-    public static boolean needNewResources(int configChanges, int interestingChanges) {
+    public static boolean needNewResources(@Config int configChanges,
+            @Config int interestingChanges) {
         return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0;
     }
 
diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java
index 40d2a82..70290c4 100644
--- a/core/java/android/content/res/ConfigurationBoundResourceCache.java
+++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java
@@ -16,6 +16,8 @@
 
 package android.content.res;
 
+import android.content.pm.ActivityInfo.Config;
+
 /**
  * A Cache class which can be used to cache resource objects that are easy to clone but more
  * expensive to inflate.
@@ -42,7 +44,7 @@
     }
 
     @Override
-    public boolean shouldInvalidateEntry(ConstantState<T> entry, int configChanges) {
+    public boolean shouldInvalidateEntry(ConstantState<T> entry, @Config int configChanges) {
         return Configuration.needNewResources(configChanges, entry.getChangingConfigurations());
     }
 }
diff --git a/core/java/android/content/res/ConstantState.java b/core/java/android/content/res/ConstantState.java
index ee609df..09d4a59 100644
--- a/core/java/android/content/res/ConstantState.java
+++ b/core/java/android/content/res/ConstantState.java
@@ -15,6 +15,8 @@
 */
 package android.content.res;
 
+import android.content.pm.ActivityInfo.Config;
+
 /**
  * A cache class that can provide new instances of a particular resource which may change
  * depending on the current {@link Resources.Theme} or {@link Configuration}.
@@ -33,7 +35,7 @@
      * Return a bit mask of configuration changes that will impact
      * this resource (and thus require completely reloading it).
      */
-    abstract public int getChangingConfigurations();
+    abstract public @Config int getChangingConfigurations();
 
     /**
      * Create a new instance without supplying resources the caller
diff --git a/core/java/android/content/res/GradientColor.java b/core/java/android/content/res/GradientColor.java
index cc46cbd..f29656a 100644
--- a/core/java/android/content/res/GradientColor.java
+++ b/core/java/android/content/res/GradientColor.java
@@ -20,6 +20,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.Resources.Theme;
 
 import com.android.internal.R;
@@ -83,7 +84,7 @@
     /** Lazily-created factory for this GradientColor. */
     private GradientColorFactory mFactory;
 
-    private int mChangingConfigurations;
+    private @Config int mChangingConfigurations;
     private int mDefaultColor;
 
     // After parsing all the attributes from XML, this shader is the ultimate result containing
@@ -506,7 +507,7 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mSrc.mChangingConfigurations;
         }
 
@@ -541,6 +542,19 @@
         return clone;
     }
 
+    /**
+     * Returns a mask of the configuration parameters for which this gradient
+     * may change, requiring that it be re-created.
+     *
+     * @return a mask of the changing configuration parameters, as defined by
+     *         {@link android.content.pm.ActivityInfo}
+     *
+     * @see android.content.pm.ActivityInfo
+     */
+    public int getChangingConfigurations() {
+        return super.getChangingConfigurations() | mChangingConfigurations;
+    }
+
     private void applyTheme(Theme t) {
         if (mThemeAttrs != null) {
             applyRootAttrsTheme(t);
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index f337fe6..fb706fc 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -54,6 +54,7 @@
 import android.view.ViewDebug;
 import android.view.ViewHierarchyEncoder;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.GrowingArrayUtils;
 import com.android.internal.util.XmlUtils;
 
@@ -62,6 +63,8 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 
 /**
  * Class for accessing an application's resources.  This sits on top of the
@@ -113,6 +116,13 @@
     final ClassLoader mClassLoader;
 
     /**
+     * WeakReferences to Themes that were constructed from this Resources object.
+     * We keep track of these in case our underlying implementation is changed, in which case
+     * the Themes must also get updated ThemeImpls.
+     */
+    private final ArrayList<WeakReference<Theme>> mThemeRefs = new ArrayList<>();
+
+    /**
      * Returns the most appropriate default theme for the specified target SDK version.
      * <ul>
      * <li>Below API 11: Gingerbread
@@ -231,10 +241,42 @@
     }
 
     /**
+     * Set the underlying implementation (containing all the resources and caches)
+     * and updates all Theme references to new implementations as well.
      * @hide
      */
     public void setImpl(ResourcesImpl impl) {
+        if (impl == mResourcesImpl) {
+            return;
+        }
+
         mResourcesImpl = impl;
+
+        // Create new ThemeImpls that are identical to the ones we have.
+        synchronized (mThemeRefs) {
+            final int count = mThemeRefs.size();
+            for (int i = 0; i < count; i++) {
+                WeakReference<Theme> weakThemeRef = mThemeRefs.get(i);
+                Theme theme = weakThemeRef != null ? weakThemeRef.get() : null;
+                if (theme != null) {
+                    theme.setImpl(mResourcesImpl.newThemeImpl(theme.getKey()));
+                }
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public ResourcesImpl getImpl() {
+        return mResourcesImpl;
+    }
+
+    /**
+     * @hide
+     */
+    public ClassLoader getClassLoader() {
+        return mClassLoader;
     }
 
     /**
@@ -1683,6 +1725,7 @@
     public final Theme newTheme() {
         Theme theme = new Theme();
         theme.setImpl(mResourcesImpl.newThemeImpl());
+        mThemeRefs.add(new WeakReference<>(theme));
         return theme;
     }
 
@@ -1785,6 +1828,7 @@
      * This is just for testing.
      * @hide
      */
+    @VisibleForTesting
     public void setCompatibilityInfo(CompatibilityInfo ci) {
         if (ci != null) {
             mResourcesImpl.updateConfiguration(null, null, ci);
@@ -2069,6 +2113,15 @@
     }
 
     /**
+     * Called by ConfigurationBoundResourceCacheTest.
+     * @hide
+     */
+    @VisibleForTesting
+    public int calcConfigChanges(Configuration config) {
+        return mResourcesImpl.calcConfigChanges(config);
+    }
+
+    /**
      * Obtains styled attributes from the theme, if available, or unstyled
      * resources if the theme is null.
      *
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 2ffd372..a364010 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -15,6 +15,9 @@
  */
 package android.content.res;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import android.animation.Animator;
 import android.animation.StateListAnimator;
 import android.annotation.AnyRes;
@@ -26,6 +29,7 @@
 import android.annotation.StyleRes;
 import android.annotation.StyleableRes;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.Resources.NotFoundException;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
@@ -40,14 +44,19 @@
 import android.util.Slog;
 import android.util.TypedValue;
 import android.util.Xml;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.InputStream;
 import java.util.Arrays;
 import java.util.Locale;
 
 /**
+ * The implementation of Resource access. This class contains the AssetManager and all caches
+ * associated with it.
+ *
+ * {@link Resources} is just a thing wrapper around this class. When a configuration change
+ * occurs, clients can retain the same {@link Resources} reference because the underlying
+ * {@link ResourcesImpl} object will be updated or re-created.
+ *
  * @hide
  */
 public class ResourcesImpl {
@@ -58,7 +67,7 @@
     private static final boolean TRACE_FOR_PRELOAD = false;
     private static final boolean TRACE_FOR_MISS_PRELOAD = false;
 
-    private static final int LAYOUT_DIR_CONFIG = ActivityInfo.activityInfoConfigToNative(
+    private static final int LAYOUT_DIR_CONFIG = ActivityInfo.activityInfoConfigJavaToNative(
             ActivityInfo.CONFIG_LAYOUT_DIRECTION);
 
     private static final int ID_OTHER = 0x01000004;
@@ -126,14 +135,14 @@
      * @param compatInfo this resource's compatibility info. Must not be null.
      */
     public ResourcesImpl(AssetManager assets, DisplayMetrics metrics, Configuration config,
-                         CompatibilityInfo compatInfo) {
+            CompatibilityInfo compatInfo) {
         mAssets = assets;
         mMetrics.setToDefaults();
         updateConfiguration(config, metrics, compatInfo);
         mAssets.ensureStringBlocks();
     }
 
-    AssetManager getAssets() {
+    public AssetManager getAssets() {
         return mAssets;
     }
 
@@ -174,7 +183,7 @@
     }
 
     void getValueForDensity(@AnyRes int id, int density, TypedValue outValue,
-                            boolean resolveRefs) throws NotFoundException {
+            boolean resolveRefs) throws NotFoundException {
         boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
         if (found) {
             return;
@@ -298,8 +307,8 @@
         return mStateListAnimatorCache;
     }
 
-    void updateConfiguration(Configuration config, DisplayMetrics metrics,
-                             CompatibilityInfo compat) {
+    public void updateConfiguration(Configuration config, DisplayMetrics metrics,
+                                    CompatibilityInfo compat) {
         synchronized (mAccessLock) {
             if (false) {
                 Slog.i(TAG, "**** Updating config of " + this + ": old config is "
@@ -324,7 +333,7 @@
             // the framework.
             mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
 
-            final int configChanges = calcConfigChanges(config);
+            final @Config int configChanges = calcConfigChanges(config);
 
             LocaleList locales = mConfiguration.getLocales();
             if (locales.isEmpty()) {
@@ -388,26 +397,30 @@
     }
 
     /**
-     * Called by ConfigurationBoundResourceCacheTest via reflection.
+     * Applies the new configuration, returning a bitmask of the changes
+     * between the old and new configurations.
+     *
+     * @param config the new configuration
+     * @return bitmask of config changes
      */
-    private int calcConfigChanges(Configuration config) {
-        int configChanges = 0xfffffff;
-        if (config != null) {
-            mTmpConfig.setTo(config);
-            int density = config.densityDpi;
-            if (density == Configuration.DENSITY_DPI_UNDEFINED) {
-                density = mMetrics.noncompatDensityDpi;
-            }
-
-            mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
-
-            if (mTmpConfig.getLocales().isEmpty()) {
-                mTmpConfig.setLocales(LocaleList.getDefault());
-            }
-            configChanges = mConfiguration.updateFrom(mTmpConfig);
-            configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
+    public @Config int calcConfigChanges(@Nullable Configuration config) {
+        if (config == null) {
+            // If there is no configuration, assume all flags have changed.
+            return 0xFFFFFFFF;
         }
-        return configChanges;
+
+        mTmpConfig.setTo(config);
+        int density = config.densityDpi;
+        if (density == Configuration.DENSITY_DPI_UNDEFINED) {
+            density = mMetrics.noncompatDensityDpi;
+        }
+
+        mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
+
+        if (mTmpConfig.getLocales().isEmpty()) {
+            mTmpConfig.setLocales(LocaleList.getDefault());
+        }
+        return mConfiguration.updateFrom(mTmpConfig);
     }
 
     /**
@@ -460,7 +473,7 @@
 
     @Nullable
     Drawable loadDrawable(Resources wrapper, TypedValue value, int id, Resources.Theme theme,
-                          boolean useCache) throws NotFoundException {
+            boolean useCache) throws NotFoundException {
         try {
             if (TRACE_FOR_PRELOAD) {
                 // Log only framework resources
@@ -553,7 +566,7 @@
     }
 
     private void cacheDrawable(TypedValue value, boolean isColorDrawable, DrawableCache caches,
-                               Resources.Theme theme, boolean usesTheme, long key, Drawable dr) {
+            Resources.Theme theme, boolean usesTheme, long key, Drawable dr) {
         final Drawable.ConstantState cs = dr.getConstantState();
         if (cs == null) {
             return;
@@ -586,8 +599,8 @@
         }
     }
 
-    private boolean verifyPreloadConfig(int changingConfigurations, int allowVarying,
-                                        int resourceId, String name) {
+    private boolean verifyPreloadConfig(@Config int changingConfigurations,
+            @Config int allowVarying, @AnyRes int resourceId, @Nullable String name) {
         // We allow preloading of resources even if they vary by font scale (which
         // doesn't impact resource selection) or density (which we handle specially by
         // simply turning off all preloading), as well as any other configs specified
@@ -625,7 +638,7 @@
      * Loads a drawable from XML or resources stream.
      */
     private Drawable loadDrawableForCookie(Resources wrapper, TypedValue value, int id,
-                                           Resources.Theme theme) {
+            Resources.Theme theme) {
         if (value.string == null) {
             throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
                     + Integer.toHexString(id) + ") is not a Drawable (color or path): " + value);
@@ -681,7 +694,7 @@
      * Last, parse the XML and generate the CSL.
      */
     private ComplexColor loadComplexColorFromName(Resources wrapper, Resources.Theme theme,
-                                                  TypedValue value, int id) {
+            TypedValue value, int id) {
         final long key = (((long) value.assetCookie) << 32) | value.data;
         final ConfigurationBoundResourceCache<ComplexColor> cache = mComplexColorCache;
         ComplexColor complexColor = cache.getInstance(key, wrapper, theme);
@@ -700,9 +713,11 @@
         }
 
         if (complexColor != null) {
+            complexColor.setBaseChangingConfigurations(value.changingConfigurations);
+
             if (mPreloading) {
-                if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
-                        "color")) {
+                if (verifyPreloadConfig(complexColor.getChangingConfigurations(),
+                        0, value.resourceId, "color")) {
                     sPreloadedComplexColors.put(key, complexColor.getConstantState());
                 }
             } else {
@@ -714,7 +729,7 @@
 
     @Nullable
     ComplexColor loadComplexColor(Resources wrapper, @NonNull TypedValue value, int id,
-                                  Resources.Theme theme) {
+            Resources.Theme theme) {
         if (TRACE_FOR_PRELOAD) {
             // Log only framework resources
             if ((id >>> 24) == 0x1) {
@@ -755,7 +770,7 @@
 
     @Nullable
     ColorStateList loadColorStateList(Resources wrapper, TypedValue value, int id,
-                                      Resources.Theme theme)
+            Resources.Theme theme)
             throws NotFoundException {
         if (TRACE_FOR_PRELOAD) {
             // Log only framework resources
@@ -815,7 +830,7 @@
      */
     @Nullable
     private ComplexColor loadComplexColorForCookie(Resources wrapper, TypedValue value, int id,
-                                                   Resources.Theme theme) {
+            Resources.Theme theme) {
         if (value.string == null) {
             throw new UnsupportedOperationException(
                     "Can't convert to ComplexColor: type=0x" + value.type);
@@ -893,8 +908,8 @@
      * @throws NotFoundException if the file could not be loaded
      */
     @NonNull
-    XmlResourceParser loadXmlResourceParser(@NonNull String file, @AnyRes int id,
-                                            int assetCookie, @NonNull String type)
+    XmlResourceParser loadXmlResourceParser(@NonNull String file, @AnyRes int id, int assetCookie,
+            @NonNull String type)
             throws NotFoundException {
         if (id != 0) {
             try {
@@ -975,6 +990,16 @@
         return new ThemeImpl();
     }
 
+    /**
+     * Creates a new ThemeImpl which is already set to the given Resources.ThemeKey.
+     */
+    ThemeImpl newThemeImpl(Resources.ThemeKey key) {
+        ThemeImpl impl = new ThemeImpl();
+        impl.mKey.setTo(key);
+        impl.rebase();
+        return impl;
+    }
+
     public class ThemeImpl {
         /**
          * Unique key for the series of styles applied to this theme.
@@ -1035,10 +1060,10 @@
 
         @NonNull
         TypedArray obtainStyledAttributes(@NonNull Resources.Theme wrapper,
-                                          AttributeSet set,
-                                          @StyleableRes int[] attrs,
-                                          @AttrRes int defStyleAttr,
-                                          @StyleRes int defStyleRes) {
+                AttributeSet set,
+                @StyleableRes int[] attrs,
+                @AttrRes int defStyleAttr,
+                @StyleRes int defStyleRes) {
             synchronized (mKey) {
                 final int len = attrs.length;
                 final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
@@ -1060,8 +1085,8 @@
 
         @NonNull
         TypedArray resolveAttributes(@NonNull Resources.Theme wrapper,
-                                     @NonNull int[] values,
-                                     @NonNull int[] attrs) {
+                @NonNull int[] values,
+                @NonNull int[] attrs) {
             synchronized (mKey) {
                 final int len = attrs.length;
                 if (values == null || len != values.length) {
@@ -1087,7 +1112,7 @@
             return mAssets.getStyleAttributes(getAppliedStyleResId());
         }
 
-        int getChangingConfigurations() {
+        @Config int getChangingConfigurations() {
             synchronized (mKey) {
                 final int nativeChangingConfig =
                         AssetManager.getThemeChangingConfigurations(mTheme);
diff --git a/core/java/android/content/res/ResourcesKey.java b/core/java/android/content/res/ResourcesKey.java
index 2620571..e894492 100644
--- a/core/java/android/content/res/ResourcesKey.java
+++ b/core/java/android/content/res/ResourcesKey.java
@@ -17,32 +17,59 @@
 package android.content.res;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.text.TextUtils;
 
+import java.util.Arrays;
 import java.util.Objects;
 
 /** @hide */
 public final class ResourcesKey {
-    private final String mResDir;
-    private final float mScale;
-    private final int mHash;
+    @Nullable
+    public final String mResDir;
+
+    @Nullable
+    public final String[] mSplitResDirs;
+
+    @Nullable
+    public final String[] mOverlayDirs;
+
+    @Nullable
+    public final String[] mLibDirs;
 
     public final int mDisplayId;
+
     @NonNull
     public final Configuration mOverrideConfiguration;
 
-    public ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration,
-            float scale) {
+    @NonNull
+    public final CompatibilityInfo mCompatInfo;
+
+    private final int mHash;
+
+    public ResourcesKey(@Nullable String resDir,
+                        @Nullable String[] splitResDirs,
+                        @Nullable String[] overlayDirs,
+                        @Nullable String[] libDirs,
+                        int displayId,
+                        @Nullable Configuration overrideConfig,
+                        @Nullable CompatibilityInfo compatInfo) {
         mResDir = resDir;
+        mSplitResDirs = splitResDirs;
+        mOverlayDirs = overlayDirs;
+        mLibDirs = libDirs;
         mDisplayId = displayId;
-        mOverrideConfiguration = overrideConfiguration != null
-                ? overrideConfiguration : Configuration.EMPTY;
-        mScale = scale;
+        mOverrideConfiguration = overrideConfig != null ? overrideConfig : Configuration.EMPTY;
+        mCompatInfo = compatInfo != null ? compatInfo : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
 
         int hash = 17;
-        hash = 31 * hash + (mResDir == null ? 0 : mResDir.hashCode());
+        hash = 31 * hash + Objects.hashCode(mResDir);
+        hash = 31 * hash + Arrays.hashCode(mSplitResDirs);
+        hash = 31 * hash + Arrays.hashCode(mOverlayDirs);
+        hash = 31 * hash + Arrays.hashCode(mLibDirs);
         hash = 31 * hash + mDisplayId;
-        hash = 31 * hash + mOverrideConfiguration.hashCode();
-        hash = 31 * hash + Float.floatToIntBits(mScale);
+        hash = 31 * hash + Objects.hashCode(mOverrideConfiguration);
+        hash = 31 * hash + Objects.hashCode(mCompatInfo);
         mHash = hash;
     }
 
@@ -60,18 +87,32 @@
         if (!(obj instanceof ResourcesKey)) {
             return false;
         }
+
         ResourcesKey peer = (ResourcesKey) obj;
+        if (mHash != peer.mHash) {
+            // If the hashes don't match, the objects can't match.
+            return false;
+        }
 
         if (!Objects.equals(mResDir, peer.mResDir)) {
             return false;
         }
+        if (!Arrays.equals(mSplitResDirs, peer.mSplitResDirs)) {
+            return false;
+        }
+        if (!Arrays.equals(mOverlayDirs, peer.mOverlayDirs)) {
+            return false;
+        }
+        if (!Arrays.equals(mLibDirs, peer.mLibDirs)) {
+            return false;
+        }
         if (mDisplayId != peer.mDisplayId) {
             return false;
         }
-        if (!mOverrideConfiguration.equals(peer.mOverrideConfiguration)) {
+        if (!Objects.equals(mOverrideConfiguration, peer.mOverrideConfiguration)) {
             return false;
         }
-        if (mScale != peer.mScale) {
+        if (!Objects.equals(mCompatInfo, peer.mCompatInfo)) {
             return false;
         }
         return true;
@@ -79,6 +120,29 @@
 
     @Override
     public String toString() {
-        return Integer.toHexString(mHash);
+        StringBuilder builder = new StringBuilder().append("ResourcesKey{");
+        builder.append(" mHash=").append(Integer.toHexString(mHash));
+        builder.append(" mResDir=").append(mResDir);
+        builder.append(" mSplitDirs=[");
+        if (mSplitResDirs != null) {
+            builder.append(TextUtils.join(",", mSplitResDirs));
+        }
+        builder.append("]");
+        builder.append(" mOverlayDirs=[");
+        if (mOverlayDirs != null) {
+            builder.append(TextUtils.join(",", mOverlayDirs));
+        }
+        builder.append("]");
+        builder.append(" mLibDirs=[");
+        if (mLibDirs != null) {
+            builder.append(TextUtils.join(",", mLibDirs));
+        }
+        builder.append("]");
+        builder.append(" mDisplayId=").append(mDisplayId);
+        builder.append(" mOverrideConfig=").append(Configuration.resourceQualifierString(
+                mOverrideConfiguration));
+        builder.append(" mCompatInfo=").append(mCompatInfo);
+        builder.append("}");
+        return builder.toString();
     }
 }
diff --git a/core/java/android/content/res/ThemedResourceCache.java b/core/java/android/content/res/ThemedResourceCache.java
index 9a2d06147..f1b1e74 100644
--- a/core/java/android/content/res/ThemedResourceCache.java
+++ b/core/java/android/content/res/ThemedResourceCache.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.Resources.Theme;
 import android.content.res.Resources.ThemeKey;
 import android.util.LongSparseArray;
@@ -115,7 +116,7 @@
      *
      * @param configChanges a bitmask of configuration changes
      */
-    public void onConfigurationChange(int configChanges) {
+    public void onConfigurationChange(@Config int configChanges) {
         prune(configChanges);
     }
 
@@ -192,7 +193,7 @@
      *                      simply prune missing weak references
      * @return {@code true} if the cache is completely empty after pruning
      */
-    private boolean prune(int configChanges) {
+    private boolean prune(@Config int configChanges) {
         synchronized (this) {
             if (mThemedEntries != null) {
                 for (int i = mThemedEntries.size() - 1; i >= 0; i--) {
@@ -211,7 +212,7 @@
     }
 
     private boolean pruneEntriesLocked(@Nullable LongSparseArray<WeakReference<T>> entries,
-            int configChanges) {
+            @Config int configChanges) {
         if (entries == null) {
             return true;
         }
@@ -226,7 +227,7 @@
         return entries.size() == 0;
     }
 
-    private boolean pruneEntryLocked(@Nullable T entry, int configChanges) {
+    private boolean pruneEntryLocked(@Nullable T entry, @Config int configChanges) {
         return entry == null || (configChanges != 0
                 && shouldInvalidateEntry(entry, configChanges));
     }
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 022bdfb..f6ac0ba 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -20,6 +20,8 @@
 import android.annotation.ColorInt;
 import android.annotation.Nullable;
 import android.annotation.StyleableRes;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ActivityInfo.Config;
 import android.graphics.drawable.Drawable;
 import android.os.StrictMode;
 import android.util.AttributeSet;
@@ -252,7 +254,8 @@
      * @throws RuntimeException if the TypedArray has already been recycled.
      * @hide
      */
-    public String getNonConfigurationString(@StyleableRes int index, int allowedChangingConfigs) {
+    public String getNonConfigurationString(@StyleableRes int index,
+            @Config int allowedChangingConfigs) {
         if (mRecycled) {
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
@@ -260,7 +263,9 @@
         index *= AssetManager.STYLE_NUM_ENTRIES;
         final int[] data = mData;
         final int type = data[index+AssetManager.STYLE_TYPE];
-        if ((data[index+AssetManager.STYLE_CHANGING_CONFIGURATIONS]&~allowedChangingConfigs) != 0) {
+        final @Config int changingConfigs = ActivityInfo.activityInfoConfigNativeToJava(
+                data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]);
+        if ((changingConfigs & ~allowedChangingConfigs) != 0) {
             return null;
         }
         if (type == TypedValue.TYPE_NULL) {
@@ -1155,12 +1160,12 @@
      * @throws RuntimeException if the TypedArray has already been recycled.
      * @see android.content.pm.ActivityInfo
      */
-    public int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         if (mRecycled) {
             throw new RuntimeException("Cannot make calls to a recycled instance!");
         }
 
-        int changingConfig = 0;
+        @Config int changingConfig = 0;
 
         final int[] data = mData;
         final int N = length();
@@ -1170,7 +1175,8 @@
             if (type == TypedValue.TYPE_NULL) {
                 continue;
             }
-            changingConfig |= data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS];
+            changingConfig |= ActivityInfo.activityInfoConfigNativeToJava(
+                    data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]);
         }
         return changingConfig;
     }
@@ -1185,7 +1191,8 @@
         outValue.data = data[index+AssetManager.STYLE_DATA];
         outValue.assetCookie = data[index+AssetManager.STYLE_ASSET_COOKIE];
         outValue.resourceId = data[index+AssetManager.STYLE_RESOURCE_ID];
-        outValue.changingConfigurations = data[index+AssetManager.STYLE_CHANGING_CONFIGURATIONS];
+        outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
+                data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]);
         outValue.density = data[index+AssetManager.STYLE_DENSITY];
         outValue.string = (type == TypedValue.TYPE_STRING) ? loadStringValueAt(index) : null;
         return true;
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index c4afbfb..b75e653 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -54,10 +54,9 @@
     private static native void nativeGetDynamicSensors(long nativeInstance, List<Sensor> list);
     private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);
 
+    private static final Object sLock = new Object();
     private static boolean sSensorModuleInitialized = false;
-    private static InjectEventQueue mInjectEventQueue = null;
-
-    private final Object mLock = new Object();
+    private static InjectEventQueue sInjectEventQueue = null;
 
     private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>();
     private List<Sensor> mFullDynamicSensorsList = new ArrayList<>();
@@ -84,24 +83,24 @@
 
     /** {@hide} */
     public SystemSensorManager(Context context, Looper mainLooper) {
+        synchronized(sLock) {
+            if (!sSensorModuleInitialized) {
+                sSensorModuleInitialized = true;
+                nativeClassInit();
+            }
+        }
+
         mMainLooper = mainLooper;
         mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
         mContext = context;
         mNativeInstance = nativeCreate(context.getOpPackageName());
 
-        synchronized(mLock) {
-            if (!sSensorModuleInitialized) {
-                sSensorModuleInitialized = true;
-                nativeClassInit();
-            }
-
-            // initialize the sensor list
-            for (int index = 0;;++index) {
-                Sensor sensor = new Sensor();
-                if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
-                mFullSensorsList.add(sensor);
-                mHandleToSensor.put(sensor.getHandle(), sensor);
-            }
+        // initialize the sensor list
+        for (int index = 0;;++index) {
+            Sensor sensor = new Sensor();
+            if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;
+            mFullSensorsList.add(sensor);
+            mHandleToSensor.put(sensor.getHandle(), sensor);
         }
     }
 
@@ -257,7 +256,7 @@
     }
 
     protected boolean initDataInjectionImpl(boolean enable) {
-        synchronized (mLock) {
+        synchronized (sLock) {
             if (enable) {
                 boolean isDataInjectionModeEnabled = nativeIsDataInjectionEnabled(mNativeInstance);
                 // The HAL does not support injection OR SensorService hasn't been set in DI mode.
@@ -266,15 +265,15 @@
                     return false;
                 }
                 // Initialize a client for data_injection.
-                if (mInjectEventQueue == null) {
-                    mInjectEventQueue = new InjectEventQueue(mMainLooper, this,
+                if (sInjectEventQueue == null) {
+                    sInjectEventQueue = new InjectEventQueue(mMainLooper, this,
                             mContext.getPackageName());
                 }
             } else {
                 // If data injection is being disabled clean up the native resources.
-                if (mInjectEventQueue != null) {
-                    mInjectEventQueue.dispose();
-                    mInjectEventQueue = null;
+                if (sInjectEventQueue != null) {
+                    sInjectEventQueue.dispose();
+                    sInjectEventQueue = null;
                 }
             }
             return true;
@@ -283,17 +282,17 @@
 
     protected boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
             long timestamp) {
-        synchronized (mLock) {
-            if (mInjectEventQueue == null) {
+        synchronized (sLock) {
+            if (sInjectEventQueue == null) {
                 Log.e(TAG, "Data injection mode not activated before calling injectSensorData");
                 return false;
             }
-            int ret = mInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy,
+            int ret = sInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy,
                                                          timestamp);
             // If there are any errors in data injection clean up the native resources.
             if (ret != 0) {
-                mInjectEventQueue.dispose();
-                mInjectEventQueue = null;
+                sInjectEventQueue.dispose();
+                sInjectEventQueue = null;
             }
             return ret == 0;
         }
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index 8724a96..38279a4 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -990,6 +990,30 @@
                 int sequenceId) {
             // default empty implementation
         }
+
+        /**
+         * <p>This method is called if a single buffer for a capture could not be sent to its
+         * destination surface.</p>
+         *
+         * <p>If the whole capture failed, then {@link #onCaptureFailed} will be called instead. If
+         * some but not all buffers were captured but the result metadata will not be available,
+         * then onCaptureFailed will be invoked with {@link CaptureFailure#wasImageCaptured}
+         * returning true, along with one or more calls to {@link #onCaptureBufferLost} for the
+         * failed outputs.</p>
+         *
+         * @param session
+         *            The session returned by {@link CameraDevice#createCaptureSession}
+         * @param request
+         *            The request that was given to the CameraDevice
+         * @param target
+         *            The target Surface that the buffer will not be produced for
+         * @param frameNumber
+         *            The frame number for the request
+         */
+        public void onCaptureBufferLost(@NonNull CameraCaptureSession session,
+                @NonNull CaptureRequest request, @NonNull Surface target, long frameNumber) {
+            // default empty implementation
+        }
     }
 
     /**
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index d58ad22..4add962 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -2070,6 +2070,24 @@
      */
     public static final int CONTROL_SCENE_MODE_FACE_PRIORITY_LOW_LIGHT = 19;
 
+    /**
+     * <p>Scene mode values within the range of
+     * <code>[DEVICE_CUSTOM_START, DEVICE_CUSTOM_END]</code> are reserved for device specific
+     * customized scene modes.</p>
+     * @see CaptureRequest#CONTROL_SCENE_MODE
+     * @hide
+     */
+    public static final int CONTROL_SCENE_MODE_DEVICE_CUSTOM_START = 100;
+
+    /**
+     * <p>Scene mode values within the range of
+     * <code>[DEVICE_CUSTOM_START, DEVICE_CUSTOM_END]</code> are reserved for device specific
+     * customized scene modes.</p>
+     * @see CaptureRequest#CONTROL_SCENE_MODE
+     * @hide
+     */
+    public static final int CONTROL_SCENE_MODE_DEVICE_CUSTOM_END = 127;
+
     //
     // Enumeration values for CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
     //
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 37d2ea2..d84a6fc 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -1116,6 +1116,11 @@
                 int sequenceId) {
             // default empty implementation
         }
+
+        public void onCaptureBufferLost(CameraDevice camera,
+                CaptureRequest request, Surface target, long frameNumber) {
+            // default empty implementation
+        }
     }
 
     /**
@@ -1887,48 +1892,66 @@
 
             final CaptureRequest request = holder.getRequest(subsequenceId);
 
-            // No way to report buffer errors right now
+            Runnable failureDispatch = null;
             if (errorCode == ERROR_CAMERA_BUFFER) {
-                Log.e(TAG, String.format("Lost output buffer reported for frame %d", frameNumber));
-                return;
-            }
-
-            boolean mayHaveBuffers = (errorCode == ERROR_CAMERA_RESULT);
-
-            // This is only approximate - exact handling needs the camera service and HAL to
-            // disambiguate between request failures to due abort and due to real errors.
-            // For now, assume that if the session believes we're mid-abort, then the error
-            // is due to abort.
-            int reason = (mCurrentSession != null && mCurrentSession.isAborting()) ?
-                    CaptureFailure.REASON_FLUSHED :
-                    CaptureFailure.REASON_ERROR;
-
-            final CaptureFailure failure = new CaptureFailure(
-                request,
-                reason,
-                /*dropped*/ mayHaveBuffers,
-                requestId,
-                frameNumber);
-
-            Runnable failureDispatch = new Runnable() {
-                @Override
-                public void run() {
-                    if (!CameraDeviceImpl.this.isClosed()){
-                        holder.getCallback().onCaptureFailed(
-                            CameraDeviceImpl.this,
-                            request,
-                            failure);
-                    }
+                final Surface outputSurface =
+                        mConfiguredOutputs.get(resultExtras.getErrorStreamId()).getSurface();
+                if (DEBUG) {
+                    Log.v(TAG, String.format("Lost output buffer reported for frame %d, target %s",
+                            frameNumber, outputSurface));
                 }
-            };
-            holder.getHandler().post(failureDispatch);
+                failureDispatch = new Runnable() {
+                    @Override
+                    public void run() {
+                        if (!CameraDeviceImpl.this.isClosed()){
+                            holder.getCallback().onCaptureBufferLost(
+                                CameraDeviceImpl.this,
+                                request,
+                                outputSurface,
+                                frameNumber);
+                        }
+                    }
+                };
+            } else {
+                boolean mayHaveBuffers = (errorCode == ERROR_CAMERA_RESULT);
 
-            // Fire onCaptureSequenceCompleted if appropriate
-            if (DEBUG) {
-                Log.v(TAG, String.format("got error frame %d", frameNumber));
+                // This is only approximate - exact handling needs the camera service and HAL to
+                // disambiguate between request failures to due abort and due to real errors.  For
+                // now, assume that if the session believes we're mid-abort, then the error is due
+                // to abort.
+                int reason = (mCurrentSession != null && mCurrentSession.isAborting()) ?
+                        CaptureFailure.REASON_FLUSHED :
+                        CaptureFailure.REASON_ERROR;
+
+                final CaptureFailure failure = new CaptureFailure(
+                    request,
+                    reason,
+                    /*dropped*/ mayHaveBuffers,
+                    requestId,
+                    frameNumber);
+
+                failureDispatch = new Runnable() {
+                    @Override
+                    public void run() {
+                        if (!CameraDeviceImpl.this.isClosed()){
+                            holder.getCallback().onCaptureFailed(
+                                CameraDeviceImpl.this,
+                                request,
+                                failure);
+                        }
+                    }
+                };
+
+                // Fire onCaptureSequenceCompleted if appropriate
+                if (DEBUG) {
+                    Log.v(TAG, String.format("got error frame %d", frameNumber));
+                }
+                mFrameNumberTracker.updateTracker(frameNumber, /*error*/true, request.isReprocess());
+                checkAndFireSequenceComplete();
             }
-            mFrameNumberTracker.updateTracker(frameNumber, /*error*/true, request.isReprocess());
-            checkAndFireSequenceComplete();
+
+            // Dispatch the failure callback
+            holder.getHandler().post(failureDispatch);
         }
 
     } // public class CameraDeviceCallbacks
diff --git a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
index d859da7..40535e2 100644
--- a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
+++ b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
@@ -28,6 +28,7 @@
     private int precaptureTriggerId;
     private long frameNumber;
     private int partialResultCount;
+    private int errorStreamId;
 
     public static final Parcelable.Creator<CaptureResultExtras> CREATOR =
             new Parcelable.Creator<CaptureResultExtras>() {
@@ -48,13 +49,14 @@
 
     public CaptureResultExtras(int requestId, int subsequenceId, int afTriggerId,
                                int precaptureTriggerId, long frameNumber,
-                               int partialResultCount) {
+                               int partialResultCount, int errorStreamId) {
         this.requestId = requestId;
         this.subsequenceId = subsequenceId;
         this.afTriggerId = afTriggerId;
         this.precaptureTriggerId = precaptureTriggerId;
         this.frameNumber = frameNumber;
         this.partialResultCount = partialResultCount;
+        this.errorStreamId = errorStreamId;
     }
 
     @Override
@@ -70,6 +72,7 @@
         dest.writeInt(precaptureTriggerId);
         dest.writeLong(frameNumber);
         dest.writeInt(partialResultCount);
+        dest.writeInt(errorStreamId);
     }
 
     public void readFromParcel(Parcel in) {
@@ -79,6 +82,7 @@
         precaptureTriggerId = in.readInt();
         frameNumber = in.readLong();
         partialResultCount = in.readInt();
+        errorStreamId = in.readInt();
     }
 
     public int getRequestId() {
@@ -104,4 +108,8 @@
     public int getPartialResultCount() {
         return partialResultCount;
     }
+
+    public int getErrorStreamId() {
+        return errorStreamId;
+    }
 }
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index 4c4adea..661edd7 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -91,11 +91,11 @@
     private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) {
         if (holder == null) {
             return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE,
-                    ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE);
+                    ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE);
         }
         return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(),
                 /*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber(),
-                /*partialResultCount*/1);
+                /*partialResultCount*/1, /*errorStreamId*/-1);
     }
 
     /**
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index 6cc7fec..dfa19b0 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -1196,7 +1196,7 @@
      *
      * <p>In particular these formats are converted:
      * <ul>
-     * <li>ImageFormat.JPEG => HAL_DATASPACE_JFIF
+     * <li>ImageFormat.JPEG => HAL_DATASPACE_V0_JFIF
      * <li>ImageFormat.DEPTH_POINT_CLOUD => HAL_DATASPACE_DEPTH
      * <li>ImageFormat.DEPTH16 => HAL_DATASPACE_DEPTH
      * <li>others => HAL_DATASPACE_UNKNOWN
@@ -1223,7 +1223,7 @@
     static int imageFormatToDataspace(int format) {
         switch (format) {
             case ImageFormat.JPEG:
-                return HAL_DATASPACE_JFIF;
+                return HAL_DATASPACE_V0_JFIF;
             case ImageFormat.DEPTH_POINT_CLOUD:
             case ImageFormat.DEPTH16:
                 return HAL_DATASPACE_DEPTH;
@@ -1633,8 +1633,16 @@
     private static final int HAL_PIXEL_FORMAT_Y16 = 0x20363159;
 
 
+    private static final int HAL_DATASPACE_STANDARD_SHIFT = 16;
+    private static final int HAL_DATASPACE_TRANSFER_SHIFT = 22;
+    private static final int HAL_DATASPACE_RANGE_SHIFT = 27;
+
     private static final int HAL_DATASPACE_UNKNOWN = 0x0;
-    private static final int HAL_DATASPACE_JFIF = 0x101;
+    private static final int HAL_DATASPACE_V0_JFIF =
+            (2 << HAL_DATASPACE_STANDARD_SHIFT) |
+            (3 << HAL_DATASPACE_TRANSFER_SHIFT) |
+            (1 << HAL_DATASPACE_RANGE_SHIFT);
+
     private static final int HAL_DATASPACE_DEPTH = 0x1000;
 
     private static final long DURATION_20FPS_NS = 50000000L;
diff --git a/core/java/android/hardware/location/ContextHubInfo.aidl b/core/java/android/hardware/location/ContextHubInfo.aidl
index 1a9221a..8de03da 100644
--- a/core/java/android/hardware/location/ContextHubInfo.aidl
+++ b/core/java/android/hardware/location/ContextHubInfo.aidl
@@ -15,7 +15,7 @@
  */
 
 package android.hardware.location;
-/*
-@hide
-*/
+/**
+ * @hide
+ */
 parcelable ContextHubInfo;
diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java
index e47c541..644e29f 100644
--- a/core/java/android/hardware/location/ContextHubInfo.java
+++ b/core/java/android/hardware/location/ContextHubInfo.java
@@ -23,7 +23,7 @@
 
 /**
  * @hide
-  */
+ */
 @SystemApi
 public class ContextHubInfo {
     private int mId;
@@ -58,6 +58,8 @@
      * set the context hub unique identifer
      *
      * @param id - unique system wide identifier for the hub
+     *
+     * @hide
      */
     public void setId(int id) {
         mId = id;
@@ -75,7 +77,9 @@
     /**
      * set a string as the hub name
      *
-     * @param String - the name for the hub
+     * @param name - the name for the hub
+     *
+     * @hide
      */
     public void setName(String name) {
         mName = name;
@@ -93,7 +97,9 @@
     /**
      * set a string as the vendor name
      *
-     * @param String - a name for the vendor
+     * @param vendor - a name for the vendor
+     *
+     * @hide
      */
     public void setVendor(String vendor) {
         mVendor = vendor;
@@ -111,7 +117,9 @@
     /**
      * set tool chain string
      *
-     * @param String - description of the tool chain
+     * @param toolchain - description of the tool chain
+     *
+     * @hide
      */
     public void setToolchain(String toolchain) {
         mToolchain = toolchain;
@@ -130,6 +138,8 @@
      * set platform version
      *
      * @param platformVersion - platform version number
+     *
+     * @hide
      */
     public void setPlatformVersion(int platformVersion) {
         mPlatformVersion = platformVersion;
@@ -148,6 +158,8 @@
      * set platform software version
      *
      * @param staticSwVersion - platform static s/w version number
+     *
+     * @hide
      */
     public void setStaticSwVersion(int staticSwVersion) {
         mStaticSwVersion = staticSwVersion;
@@ -166,6 +178,8 @@
      * set the tool chain version number
      *
      * @param toolchainVersion - tool chain version number
+     *
+     * @hide
      */
     public void setToolchainVersion(int toolchainVersion) {
         mToolchainVersion = toolchainVersion;
@@ -184,6 +198,8 @@
      * set the peak mips that this hub can support
      *
      * @param peakMips - peak mips this hub can deliver
+     *
+     * @hide
      */
     public void setPeakMips(float peakMips) {
         mPeakMips = peakMips;
@@ -206,6 +222,8 @@
      * Set the power consumed by the hub in stopped state
      *
      * @param stoppedPowerDrawMw - stopped power in milli watts
+     *
+     * @hide
      */
     public void setStoppedPowerDrawMw(float stoppedPowerDrawMw) {
         mStoppedPowerDrawMw = stoppedPowerDrawMw;
@@ -230,6 +248,8 @@
      * Set the sleep power draw in milliwatts
      *
      * @param sleepPowerDrawMw - sleep power draw in milliwatts.
+     *
+     * @hide
      */
     public void setSleepPowerDrawMw(float sleepPowerDrawMw) {
         mSleepPowerDrawMw = sleepPowerDrawMw;
@@ -250,6 +270,8 @@
      *
      * @param peakPowerDrawMw - peak power draw of the hub in
      *                        milliwatts.
+     *
+     * @hide
      */
     public void setPeakPowerDrawMw(float peakPowerDrawMw) {
         mPeakPowerDrawMw = peakPowerDrawMw;
@@ -281,6 +303,8 @@
      * set the supported sensors on this hub
      *
      * @param supportedSensors - supported sensors on this hub
+     *
+     * @hide
      */
     public void setSupportedSensors(int[] supportedSensors) {
         mSupportedSensors = Arrays.copyOf(supportedSensors, supportedSensors.length);
@@ -292,6 +316,8 @@
      * @param memoryRegions - memory regions information
      *
      * @see MemoryRegion
+     *
+     * @hide
      */
     public void setMemoryRegions(MemoryRegion[] memoryRegions) {
         mMemoryRegions = Arrays.copyOf(memoryRegions, memoryRegions.length);
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 301b2e4..8deded2 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -16,26 +16,19 @@
 package android.hardware.location;
 
 import android.annotation.SystemApi;
-import android.hardware.location.NanoAppInstanceInfo;
-import android.content.ComponentName;
 import android.content.Context;
-import android.content.ServiceConnection;
-import android.Manifest;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.util.Log;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-
 /**
- * A class that exposes the Context hubs on a device to
- * applicaions.
+ * A class that exposes the Context hubs on a device to applications.
  *
- * Please not that this class is not expected to be used by
- * unbundled applications. Also, calling applications are
- * expected to have LOCTION_HARDWARE premissions to use this
- * class.
+ * Please note that this class is not expected to be used by unbundled applications. Also, calling
+ * applications are expected to have LOCATION_HARDWARE permissions to use this class.
  *
  * @hide
  */
@@ -43,18 +36,14 @@
 public final class ContextHubManager {
 
     private static final String TAG = "ContextHubManager";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
-    private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
-            + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
 
-    private Context mContext;
+    private final Looper mMainLooper;
     private IContextHubService mContextHubService;
-    private boolean mContextHubConnected;
+    private ContextHubCallback mCallback;
+    private Handler mCallbackHandler;
 
     /**
-     * A special context hub identifer meaning any possible hub on
-     * the system.
+     * A special context hub identifier meaning any possible hub on the system.
      */
     public static final int ANY_HUB       = -1;
     /**
@@ -70,19 +59,37 @@
      */
     public static final int MSG_DATA_SEND       = 3;
 
+    /**
+     * An interface to receive asynchronous communication from the context hub.
+     */
+    public abstract static class ContextHubCallback {
+        protected ContextHubCallback() {}
+
+        /**
+         * Callback function called on message receipt from context hub.
+         *
+         * @param hubHandle Handle (system-wide unique identifier) of the hub of the message.
+         * @param nanoAppHandle Handle (unique identifier) for the app that sent the message.
+         * @param message The context hub message.
+         *
+         * @see ContextHubMessage
+         */
+        public abstract void onMessageReceipt(
+                int hubHandle,
+                int nanoAppHandle,
+                ContextHubMessage message);
+    }
 
     /**
      * Get a handle to all the context hubs in the system
      * @return array of context hub handles
      */
-    public int[] getContexthubHandles() {
+    public int[] getContextHubHandles() {
         int[] retVal = null;
-        if(mContextHubConnected) {
-            try {
-                retVal = mContextHubService.getContextHubHandles();
-            }catch (RemoteException e) {
-                Log.e (TAG, "Could not fetch context hub handles :" + e.toString());
-            }
+        try {
+            retVal = getBinder().getContextHubHandles();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not fetch context hub handles : " + e);
         }
         return retVal;
     }
@@ -90,27 +97,24 @@
     /**
      * Get more information about a specific hub.
      *
-     * @param contexthubHandle Handle of context hub
-     *
-     * @return ContextHubInfo  returned information about the hub
+     * @param hubHandle Handle (system-wide unique identifier) of a context hub.
+     * @return ContextHubInfo Information about the requested context hub.
      *
      * @see ContextHubInfo
      */
-    public ContextHubInfo getContexthubInfo(int contexthubHandle) {
+    public ContextHubInfo getContextHubInfo(int hubHandle) {
         ContextHubInfo retVal = null;
-        if(mContextHubConnected) {
-            try {
-                retVal = mContextHubService.getContextHubInfo(contexthubHandle);
-            }catch (RemoteException e) {
-                Log.e (TAG, "Could not fetch context hub info :" + e.toString());
-            }
+        try {
+            retVal = getBinder().getContextHubInfo(hubHandle);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not fetch context hub info :" + e);
         }
 
-        return(retVal);
+        return retVal;
     }
 
     /**
-     * Load a nanoapp on a specified context hub
+     * Load a nano app on a specified context hub.
      *
      * @param hubHandle handle of context hub to load the app on.
      * @param app the nanoApp to load on the hub
@@ -122,13 +126,14 @@
      */
     public int loadNanoApp(int hubHandle, NanoApp app) {
         int retVal = -1;
+        if (app == null) {
+            return retVal;
+        }
 
-        if(mContextHubConnected) {
-            try {
-                retVal = mContextHubService.loadNanoApp(hubHandle, app);
-            }catch (RemoteException e) {
-                Log.e (TAG, "Could not fetch load nanoApp :" + e.toString());
-            }
+        try {
+            retVal = getBinder().loadNanoApp(hubHandle, app);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not fetch load nanoApp :" + e);
         }
 
         return retVal;
@@ -137,19 +142,17 @@
     /**
      * Unload a specified nanoApp
      *
-     * @param nanoAppInstanceHandle handle of the nanoApp to load
+     * @param nanoAppHandle handle of the nanoApp to load
      *
-     * @return int  0 on success, -1 otherewise
+     * @return int  0 on success, -1 otherwise
      */
-    public int unloadNanoApp(int nanoAppInstanceHandle) {
+    public int unloadNanoApp(int nanoAppHandle) {
         int retVal = -1;
 
-        if(mContextHubConnected) {
-            try {
-                retVal = mContextHubService.unloadNanoApp(nanoAppInstanceHandle);
-            }catch (RemoteException e) {
-                Log.e (TAG, "Could not fetch unload nanoApp :" + e.toString());
-            }
+        try {
+            retVal = getBinder().unloadNanoApp(nanoAppHandle);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not fetch unload nanoApp :" + e);
         }
 
         return retVal;
@@ -158,22 +161,18 @@
     /**
      * get information about the nano app instance
      *
-     * @param nanoAppInstanceHandle handle of the nanoAppInstance
-     *
-     * @return NanoAppInstanceInfo Inforamtion about the nano app
-     *         instance.
+     * @param nanoAppHandle handle of the nanoAppInstance
+     * @return NanoAppInstanceInfo Information about the nano app instance.
      *
      * @see NanoAppInstanceInfo
      */
-    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) {
+    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
         NanoAppInstanceInfo retVal = null;
 
-        if(mContextHubConnected) {
-            try {
-                retVal = mContextHubService.getNanoAppInstanceInfo(nanoAppInstanceHandle);
-            }catch (RemoteException e) {
-                Log.e (TAG, "Could not fetch nanoApp info :" + e.toString());
-            }
+        try {
+            retVal = getBinder().getNanoAppInstanceInfo(nanoAppHandle);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not fetch nanoApp info :" + e);
         }
 
         return retVal;
@@ -187,92 +186,143 @@
      *
      * @see NanoAppFilter
      *
-     * @return Integer[] Array of handles to any found nano apps
+     * @return int[] Array of handles to any found nano apps
      */
-    public Integer[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
-        int[] temp;
-        Integer[] retVal = null;
+    public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
+        int[] retVal = null;
+        try {
+            retVal = getBinder().findNanoAppOnHub(hubHandle, filter);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not query nanoApp instance :" + e);
+        }
+        return retVal;
+    }
 
-        if(mContextHubConnected) {
-            try {
-                temp = mContextHubService.findNanoAppOnHub(hubHandle, filter);
-                retVal = new Integer[temp.length];
-                for (int i = 0; i < temp.length; i++) {
-                    retVal[i] = temp[i];
-                }
-            }catch (RemoteException e) {
-                Log.e (TAG, "Could not query nanoApp instance :" + e.toString());
-            }
+    /**
+     * Send a message to a specific nano app instance on a context hub.
+     *
+     * @param hubHandle handle of the hub to send the message to
+     * @param nanoAppHandle  handle of the nano app to send to
+     * @param message Message to be sent
+     *
+     * @see ContextHubMessage
+     *
+     * @return int 0 on success, -1 otherwise
+     */
+    public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage message) {
+        int retVal = -1;
+
+        try {
+            retVal = getBinder().sendMessage(hubHandle, nanoAppHandle, message);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not fetch send message :" + e.toString());
         }
 
         return retVal;
     }
 
     /**
-     * Send a message to a spcific nano app instance on a context
-     * hub
+     * Set a callback to receive messages from the context hub
      *
+     * @param callback Callback object
      *
-     * @param hubHandle handle of the hub to send the message to
-     * @param nanoAppHandle  handle of the nano app to send to
-     * @param msg Message to be sent
-     *
-     * @see ContextHubMessage
+     * @see ContextHubCallback
      *
      * @return int 0 on success, -1 otherwise
      */
-    public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg) {
-        int retVal = -1;
-
-        if(mContextHubConnected) {
-            try {
-                retVal = mContextHubService.sendMessage(hubHandle, nanoAppHandle, msg);
-            }catch (RemoteException e) {
-                Log.e (TAG, "Could not fetch send message :" + e.toString());
-            }
-        }
-
-        return retVal;
+    public int registerContextHubCallback(ContextHubCallback callback) {
+        return registerContextHubCallback(callback, null);
     }
 
-    private void checkPermissions() {
-        mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
+    /**
+     * Set a callback to receive messages from the context hub
+     *
+     * @param callback Callback object
+     * @param handler Handler object
+     *
+     * @see ContextHubCallback
+     *
+     * @return int 0 on success, -1 otherwise
+     */
+    public int registerContextHubCallback(ContextHubCallback callback, Handler handler) {
+        synchronized(this) {
+            if (mCallback != null) {
+                Log.e(TAG, "Max number of callbacks reached!");
+                return -1;
+            }
+            mCallback = callback;
+            mCallbackHandler = handler;
+        }
+        return 0;
+    }
+
+    /**
+     * Unregister a callback for receive messages from the context hub.
+     *
+     * @see ContextHubCallback
+     *
+     * @param callback method to deregister
+     *
+     * @return int 0 on success, -1 otherwise
+     */
+    public int unregisterContextHubCallback(ContextHubCallback callback) {
+      synchronized(this) {
+          if (callback != mCallback) {
+              Log.e(TAG, "Cannot recognize callback!");
+              return -1;
+          }
+
+          mCallback = null;
+          mCallbackHandler = null;
+      }
+      return 0;
     }
 
     private IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
         @Override
-        public void onMessageReceipt(int hubId, int nanoAppId, ContextHubMessage msg) throws RemoteException {
-
+        public void onMessageReceipt(final int hubId, final int nanoAppId,
+                final ContextHubMessage message) {
+            if (mCallback != null) {
+                synchronized(this) {
+                    final ContextHubCallback callback = mCallback;
+                    Handler handler = mCallbackHandler == null ?
+                            new Handler(mMainLooper) : mCallbackHandler;
+                    handler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            callback.onMessageReceipt(hubId, nanoAppId, message);
+                        }
+                    });
+                }
+            } else {
+                Log.d(TAG, "Context hub manager client callback is NULL");
+            }
         }
     };
 
-    private ContextHubManager(Context context) {
-        checkPermissions();
-        mContext = context;
-        mContextHubConnected = false;
+    /** @hide */
+    public ContextHubManager(Context context, Looper mainLooper) {
+        mMainLooper = mainLooper;
+
+        IBinder b = ServiceManager.getService(ContextHubService.CONTEXTHUB_SERVICE);
+        if (b != null) {
+            mContextHubService = IContextHubService.Stub.asInterface(b);
+
+            try {
+                getBinder().registerCallback(mClientCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Could not register callback:" + e);
+            }
+
+        } else {
+            Log.d(TAG, "failed to getService");
+        }
     }
 
-    private ServiceConnection mServiceConnection = new ServiceConnection() {
-        @Override
-        public void onServiceConnected(ComponentName name, IBinder service) {
-            mContextHubService = IContextHubService.Stub.asInterface(service);
-            mContextHubConnected = true;
-
-            // Register our Callback
-            try {
-                mContextHubService.registerCallBack(mClientCallback);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Could not register callback with context hub service :" + e.toString());
-            }
-            Log.d(TAG, "contexthub manager connected to " + name.toString());
+    private IContextHubService getBinder() throws RemoteException {
+        if (mContextHubService == null) {
+            throw new RemoteException("Service not connected.");
         }
-
-        @Override
-        public void onServiceDisconnected(ComponentName name) {
-            mContextHubService = null;
-            mContextHubConnected = false;
-            Log.d(TAG, "contexthub manager disconnected from " + name.toString());
-        }
-    };
-
+        return mContextHubService;
+    }
 }
diff --git a/core/java/android/hardware/location/ContextHubMessage.aidl b/core/java/android/hardware/location/ContextHubMessage.aidl
index 915f1ec..56704e7 100644
--- a/core/java/android/hardware/location/ContextHubMessage.aidl
+++ b/core/java/android/hardware/location/ContextHubMessage.aidl
@@ -15,8 +15,8 @@
  */
 
 package android.hardware.location;
-/*
-@hide
-*/
+/**
+ * @hide
+ */
 parcelable ContextHubMessage;
 
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
index a2a13c6..274babe 100644
--- a/core/java/android/hardware/location/ContextHubService.java
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -16,10 +16,8 @@
 
 package android.hardware.location;
 
-import android.app.Service;
+import android.Manifest;
 import android.content.Context;
-import android.content.Intent;
-import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -29,175 +27,174 @@
 /**
  * @hide
  */
-public class ContextHubService extends Service {
+public class ContextHubService extends IContextHubService.Stub {
 
     private static final String TAG = "ContextHubService";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
+    private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
+            + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
 
-    private static ContextHubService sSingletonInstance;
-    private static final Object sSingletonInstanceLock = new Object();
+    public static final String CONTEXTHUB_SERVICE = "contexthub_service";
 
-    private HashMap<Integer, ContextHubInfo> mHubHash;
+    private final Context mContext;
+
     private HashMap<Integer, NanoAppInstanceInfo> mNanoAppHash;
-    private ContextHubInfo[] mContexthubInfo;
+    private ContextHubInfo[] mContextHubInfo;
+    private IContextHubCallback mCallback;
 
+    public ContextHubService(Context context) {
+        mContext = context;
+        mContextHubInfo = nativeInitialize();
+
+        for (int i = 0; i < mContextHubInfo.length; i++) {
+            Log.v(TAG, "ContextHub[" + i + "] id: " + mContextHubInfo[i].getId()
+                  + ", name:  " + mContextHubInfo[i].getName());
+        }
+    }
 
     private native int nativeSendMessage(int[] header, byte[] data);
     private native ContextHubInfo[] nativeInitialize();
 
-    private int onMessageReceipt(int[] header, byte[] data) {
+    @Override
+    public int registerCallback(IContextHubCallback callback) throws RemoteException{
+        checkPermissions();
+        mCallback = callback;
         return 0;
     }
-    private void initialize() {
-        mContexthubInfo = nativeInitialize();
 
-        mHubHash = new HashMap<Integer, ContextHubInfo>();
 
-        for (int i = 0; i < mContexthubInfo.length; i++) {
-            mHubHash.put(i + 1, mContexthubInfo[i]); // Avoiding zero
-        }
-    }
+    private int onMessageReceipt(int[] header, byte[] data) {
+        if (mCallback != null) {
+            // TODO : Defend against unexpected header sizes
+            //        Add abstraction for magic numbers
+            //        onMessageRecipt should pass the right arguments
+            ContextHubMessage msg = new ContextHubMessage(header[0], header[1], data);
 
-    private ContextHubService(Context context) {
-        initialize();
-        Log.d(TAG, "Created from " + context.toString());
-    }
-
-    public static ContextHubService getInstance(Context context) {
-        synchronized (sSingletonInstanceLock) {
-            if (sSingletonInstance == null) {
-                sSingletonInstance = new ContextHubService(context);
+            try {
+                mCallback.onMessageReceipt(0, 0, msg);
+            } catch (Exception e) {
+                Log.e(TAG, "Exception " + e + " when calling remote callback");
+                return -1;
             }
-            return sSingletonInstance;
+        } else {
+            Log.d(TAG, "Message Callback is NULL");
+        }
+
+        return 0;
+    }
+
+    @Override
+    public int[] getContextHubHandles() throws RemoteException {
+        checkPermissions();
+        int [] returnArray = new int[mContextHubInfo.length];
+
+        for (int i = 0; i < returnArray.length; ++i) {
+            returnArray[i] = i + 1; //valid handles from 1...n
+            Log.d(TAG, String.format("Hub %s is mapped to %d",
+                                     mContextHubInfo[i].getName(), returnArray[i]));
+        }
+
+        return returnArray;
+    }
+
+    @Override
+    public ContextHubInfo getContextHubInfo(int contextHubHandle) throws RemoteException {
+        checkPermissions();
+        contextHubHandle -= 1;
+        if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
+            return null; // null means fail
+        }
+
+        return mContextHubInfo[contextHubHandle];
+    }
+
+    @Override
+    public int loadNanoApp(int contextHubHandle, NanoApp app) throws RemoteException {
+        checkPermissions();
+        contextHubHandle -= 1;
+
+        if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
+            return -1; // negative handle are invalid, means failed
+        }
+
+        // Call Native interface here
+        int[] msgHeader = new int[8];
+        msgHeader[0] = contextHubHandle;
+        msgHeader[1] = app.getAppId();
+        msgHeader[2] = app.getAppVersion();
+        msgHeader[3] = ContextHubManager.MSG_LOAD_NANO_APP;
+        msgHeader[4] = 0; // Loading hints
+
+        return nativeSendMessage(msgHeader, app.getAppBinary());
+    }
+
+    @Override
+    public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException {
+        checkPermissions();
+        NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstanceHandle);
+        if (info == null) {
+            return -1; //means failed
+        }
+
+        // Call Native interface here
+        int[] msgHeader = new int[8];
+        msgHeader[0] = info.getContexthubId();
+        msgHeader[1] = ContextHubManager.MSG_UNLOAD_NANO_APP;
+        msgHeader[2] = info.getHandle();
+
+        return nativeSendMessage(msgHeader, null);
+    }
+
+    @Override
+    public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle)
+            throws RemoteException {
+        checkPermissions();
+        // This assumes that all the nanoAppInfo is current. This is reasonable
+        // for the use cases for tightly controlled nanoApps.
+        if (mNanoAppHash.containsKey(nanoAppInstanceHandle)) {
+            return mNanoAppHash.get(nanoAppInstanceHandle);
+        } else {
+            return null;
         }
     }
 
     @Override
-    public void onCreate() {
-        super.onCreate();
+    public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) throws RemoteException {
+        checkPermissions();
+        ArrayList<Integer> foundInstances = new ArrayList<Integer>();
+
+        for(Integer nanoAppInstance : mNanoAppHash.keySet()) {
+            NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstance);
+
+            if(filter.testMatch(info)){
+                foundInstances.add(nanoAppInstance);
+            }
+        }
+
+        int[] retArray = new int[foundInstances.size()];
+        for (int i = 0; i < foundInstances.size(); i++) {
+            retArray[i] = foundInstances.get(i).intValue();
+        }
+
+        return retArray;
     }
 
     @Override
-    public IBinder onBind(Intent intent) {
-        return null;
+    public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg)
+            throws RemoteException {
+        checkPermissions();
+        int[] msgHeader = new int[8];
+        msgHeader[0] = ContextHubManager.MSG_DATA_SEND;
+        msgHeader[1] = hubHandle;
+        msgHeader[2] = nanoAppHandle;
+        msgHeader[3] = msg.getMsgType();
+        msgHeader[4] = msg.getVersion();
+
+        return nativeSendMessage(msgHeader, msg.getData());
     }
 
-    private final IContextHubService.Stub mBinder = new IContextHubService.Stub() {
-
-        private  IContextHubCallback callback;
-
-        @Override
-        public int registerCallBack(IContextHubCallback callback) throws RemoteException{
-            this.callback = callback;
-            return 0;
-        }
-
-        @Override
-        public int[] getContextHubHandles() throws RemoteException {
-            int [] returnArray = new int[mHubHash.size()];
-            int i = 0;
-            for (int key : mHubHash.keySet()) {
-                // Add any filtering here
-                returnArray[i] = key;
-                i++;
-            }
-            return returnArray;
-        }
-
-        @Override
-        public ContextHubInfo getContextHubInfo(int contexthubHandle) throws RemoteException {
-            return mHubHash.get(contexthubHandle);
-        }
-
-        @Override
-        public int loadNanoApp(int hubHandle, NanoApp app) throws RemoteException {
-            if (!mHubHash.containsKey(hubHandle)) {
-                return -1;
-            } else {
-                // Call Native interface here
-                int[] msgHeader = new int[8];
-                msgHeader[0] = ContextHubManager.MSG_LOAD_NANO_APP;
-                msgHeader[1] = app.getAppId();
-                msgHeader[2] = app.getAppVersion();
-                msgHeader[3] = 0; // LOADING_HINTS
-                msgHeader[4] = hubHandle;
-
-                int handle = nativeSendMessage(msgHeader, app.getAppBinary());
-
-                // if successful, add an entry to mNanoAppHash
-
-                if(handle > 0) {
-                    return 0;
-                } else {
-
-                    return -1;
-                }
-            }
-        }
-
-        @Override
-        public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException {
-            if(!mNanoAppHash.containsKey(nanoAppInstanceHandle)) {
-                return -1;
-            } else {
-                NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstanceHandle);
-                // Call Native interface here
-                int[] msgHeader = new int[8];
-                msgHeader[0] = ContextHubManager.MSG_UNLOAD_NANO_APP;
-                msgHeader[1] = info.getContexthubId();
-                msgHeader[2] = info.getHandle();
-
-                int result = nativeSendMessage(msgHeader, null);
-                // if successful, remove the entry in mNanoAppHash
-                if(result == 0) {
-                    mNanoAppHash.remove(nanoAppInstanceHandle);
-                }
-                return(result);
-            }
-        }
-
-        @Override
-        public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) throws RemoteException {
-            // This assumes that all the nanoAppInfo is current. This is reasonable
-            // for the use cases for tightly controlled nanoApps.
-            //
-            if(!mNanoAppHash.containsKey(nanoAppInstanceHandle)) {
-                return(mNanoAppHash.get(nanoAppInstanceHandle));
-            } else {
-                return null;
-            }
-        }
-
-        @Override
-        public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) throws RemoteException {
-            ArrayList<Integer> foundInstances = new ArrayList<Integer>();
-
-            for(Integer nanoAppInstance : mNanoAppHash.keySet()) {
-                NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstance);
-
-                if(filter.testMatch(info)){
-                    foundInstances.add(nanoAppInstance);
-                }
-            }
-
-            int[] retArray = new int[foundInstances.size()];
-            for (int i = 0; i < foundInstances.size(); i++) {
-                retArray[i] = foundInstances.get(i).intValue();
-            }
-
-            return retArray;
-        }
-
-        @Override
-        public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg) throws RemoteException {
-            int[] msgHeader = new int[8];
-            msgHeader[0] = ContextHubManager.MSG_DATA_SEND;
-            msgHeader[1] = hubHandle;
-            msgHeader[2] = nanoAppHandle;
-            msgHeader[3] = msg.getMsgType();
-            msgHeader[4] = msg.getVersion();
-
-            return (nativeSendMessage(msgHeader, msg.getData()));
-        }
-    };
+    private void checkPermissions() {
+        mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
+    }
 }
+
diff --git a/core/java/android/hardware/location/IContextHubCallback.aidl b/core/java/android/hardware/location/IContextHubCallback.aidl
index 45b1ef4..141fcf6 100644
--- a/core/java/android/hardware/location/IContextHubCallback.aidl
+++ b/core/java/android/hardware/location/IContextHubCallback.aidl
@@ -18,7 +18,9 @@
 
 import android.hardware.location.ContextHubMessage;
 
-/** @hide */
+/**
+ * @hide
+ */
 oneway interface IContextHubCallback {
     void onMessageReceipt(int hubId, int nanoAppId, in ContextHubMessage msg);
 }
diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl
index b2db0b2..ff8c1d0 100644
--- a/core/java/android/hardware/location/IContextHubService.aidl
+++ b/core/java/android/hardware/location/IContextHubService.aidl
@@ -24,11 +24,13 @@
 import android.hardware.location.NanoAppFilter;
 import android.hardware.location.IContextHubCallback;
 
-/** @hide */
+/**
+ * @hide
+ */
 interface IContextHubService {
 
     // register a callback to receive messages
-    int registerCallBack(in IContextHubCallback callback);
+    int registerCallback(in IContextHubCallback callback);
 
     // Gets a list of available context hub handles
     int[] getContextHubHandles();
diff --git a/core/java/android/hardware/location/MemoryRegion.java b/core/java/android/hardware/location/MemoryRegion.java
index e8c7615..d100de2 100644
--- a/core/java/android/hardware/location/MemoryRegion.java
+++ b/core/java/android/hardware/location/MemoryRegion.java
@@ -23,7 +23,6 @@
 /**
  * @hide
  */
-
 @SystemApi
 public class MemoryRegion implements Parcelable{
 
diff --git a/core/java/android/hardware/location/NanoApp.aidl b/core/java/android/hardware/location/NanoApp.aidl
index d32c44a..9df9a08 100644
--- a/core/java/android/hardware/location/NanoApp.aidl
+++ b/core/java/android/hardware/location/NanoApp.aidl
@@ -15,7 +15,7 @@
  */
 
 package android.hardware.location;
-/*
-@hide
-*/
+/**
+ * @hide
+ */
 parcelable NanoApp;
diff --git a/core/java/android/hardware/location/NanoApp.java b/core/java/android/hardware/location/NanoApp.java
index 36d181f..b447b62 100644
--- a/core/java/android/hardware/location/NanoApp.java
+++ b/core/java/android/hardware/location/NanoApp.java
@@ -13,16 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package android.hardware.location;
 
-
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-/**
- * A class describing nano apps.
+/** A class describing nano apps.
  * A nano app is a piece of executable code that can be
  * downloaded onto a specific architecture. These are targtted
  * for low power compute domains on a device.
diff --git a/core/java/android/hardware/location/NanoAppFilter.aidl b/core/java/android/hardware/location/NanoAppFilter.aidl
index cc6d475..5f10201 100644
--- a/core/java/android/hardware/location/NanoAppFilter.aidl
+++ b/core/java/android/hardware/location/NanoAppFilter.aidl
@@ -15,7 +15,7 @@
  */
 
 package android.hardware.location;
-/*
-@hide
-*/
+/**
+ * @hide
+ */
 parcelable NanoAppFilter;
diff --git a/core/java/android/hardware/location/NanoAppFilter.java b/core/java/android/hardware/location/NanoAppFilter.java
index ac341e4..369f9e4 100644
--- a/core/java/android/hardware/location/NanoAppFilter.java
+++ b/core/java/android/hardware/location/NanoAppFilter.java
@@ -110,8 +110,9 @@
         return true;
     }
     /**
+     * Test match method.
      *
-     * @param nano app instance info
+     * @param info nano app instance info
      *
      * @return true if this is a match, false otherwise
      */
diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.aidl b/core/java/android/hardware/location/NanoAppInstanceInfo.aidl
index c8c40d7..2db5566 100644
--- a/core/java/android/hardware/location/NanoAppInstanceInfo.aidl
+++ b/core/java/android/hardware/location/NanoAppInstanceInfo.aidl
@@ -15,7 +15,7 @@
  */
 
 package android.hardware.location;
-/*
-@hide
-*/
-parcelable NanoAppInstanceInfo;
\ No newline at end of file
+/**
+ * @hide
+ */
+parcelable NanoAppInstanceInfo;
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 2826882..6b79a8a 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -2269,8 +2269,9 @@
     public void onExtractedDeleteText(int start, int end) {
         InputConnection conn = getCurrentInputConnection();
         if (conn != null) {
+            conn.finishComposingText();
             conn.setSelection(start, start);
-            conn.deleteSurroundingText(0, end-start);
+            conn.deleteSurroundingText(0, end - start);
         }
     }
 
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 3d8b091..25806fa 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -71,9 +71,9 @@
     /** {@link #set} value for all roaming values. */
     public static final int ROAMING_ALL = -1;
     /** {@link #set} value where native, non-roaming data is accounted. */
-    public static final int ROAMING_DEFAULT = 0;
+    public static final int ROAMING_NO = 0;
     /** {@link #set} value where roaming data is accounted. */
-    public static final int ROAMING_ROAMING = 1;
+    public static final int ROAMING_YES = 1;
 
     // TODO: move fields to "mVariable" notation
 
@@ -123,7 +123,7 @@
 
         public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets,
                 long txBytes, long txPackets, long operations) {
-            this(iface, uid, set, tag, ROAMING_DEFAULT, rxBytes, rxPackets, txBytes, txPackets,
+            this(iface, uid, set, tag, ROAMING_NO, rxBytes, rxPackets, txBytes, txPackets,
                     operations);
         }
 
@@ -836,10 +836,10 @@
         switch (roaming) {
             case ROAMING_ALL:
                 return "ALL";
-            case ROAMING_DEFAULT:
-                return "DEFAULT";
-            case ROAMING_ROAMING:
-                return "ROAMING";
+            case ROAMING_NO:
+                return "NO";
+            case ROAMING_YES:
+                return "YES";
             default:
                 return "UNKNOWN";
         }
@@ -1019,18 +1019,18 @@
         // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
         // the TAG_NONE traffic.
         //
-        // Relies on the fact that the underlying traffic only has state ROAMING_DEFAULT, which
+        // Relies on the fact that the underlying traffic only has state ROAMING_NO, which
         // should be the case as it comes directly from the /proc file. We only blend in the
         // roaming data after applying these adjustments, by checking the NetworkIdentity of the
         // underlying iface.
         int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE,
-                ROAMING_DEFAULT);
+                ROAMING_NO);
         if (idxVpnBackground != -1) {
             tunSubtract(idxVpnBackground, this, moved);
         }
 
         int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE,
-                ROAMING_DEFAULT);
+                ROAMING_NO);
         if (idxVpnForeground != -1) {
             tunSubtract(idxVpnForeground, this, moved);
         }
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index ba8bd34..95ffb44 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -19,6 +19,7 @@
 import android.annotation.SystemApi;
 import android.app.DownloadManager;
 import android.app.backup.BackupManager;
+import android.app.usage.NetworkStatsManager;
 import android.content.Context;
 import android.media.MediaPlayer;
 import android.os.RemoteException;
@@ -33,12 +34,16 @@
 import java.net.SocketException;
 
 /**
- * Class that provides network traffic statistics.  These statistics include
+ * Class that provides network traffic statistics. These statistics include
  * bytes transmitted and received and network packets transmitted and received,
  * over all interfaces, over the mobile interface, and on a per-UID basis.
  * <p>
- * These statistics may not be available on all platforms.  If the statistics
- * are not supported by this device, {@link #UNSUPPORTED} will be returned.
+ * These statistics may not be available on all platforms. If the statistics are
+ * not supported by this device, {@link #UNSUPPORTED} will be returned.
+ * <p>
+ * Note that the statistics returned by this class reset and start from zero
+ * after every reboot. To access more robust historical network statistics data,
+ * use {@link NetworkStatsManager} instead.
  */
 public class TrafficStats {
     /**
@@ -497,14 +502,27 @@
      * monotonically since device boot. Statistics are measured at the network
      * layer, so they include both TCP and UDP usage.
      * <p>
-     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
-     * {@link #UNSUPPORTED} on devices where statistics aren't available.
+     * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may
+     * return {@link #UNSUPPORTED} on devices where statistics aren't available.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
+     * report traffic statistics for the calling UID. It will return
+     * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
+     * historical network statistics belonging to other UIDs, use
+     * {@link NetworkStatsManager}.
      *
      * @see android.os.Process#myUid()
      * @see android.content.pm.ApplicationInfo#uid
      */
     public static long getUidTxBytes(int uid) {
-        return nativeGetUidStat(uid, TYPE_TX_BYTES);
+        // This isn't actually enforcing any security; it just returns the
+        // unsupported value. The real filtering is done at the kernel level.
+        final int callingUid = android.os.Process.myUid();
+        if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
+            return nativeGetUidStat(uid, TYPE_TX_BYTES);
+        } else {
+            return UNSUPPORTED;
+        }
     }
 
     /**
@@ -515,12 +533,25 @@
      * <p>
      * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
      * {@link #UNSUPPORTED} on devices where statistics aren't available.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
+     * report traffic statistics for the calling UID. It will return
+     * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
+     * historical network statistics belonging to other UIDs, use
+     * {@link NetworkStatsManager}.
      *
      * @see android.os.Process#myUid()
      * @see android.content.pm.ApplicationInfo#uid
      */
     public static long getUidRxBytes(int uid) {
-        return nativeGetUidStat(uid, TYPE_RX_BYTES);
+        // This isn't actually enforcing any security; it just returns the
+        // unsupported value. The real filtering is done at the kernel level.
+        final int callingUid = android.os.Process.myUid();
+        if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
+            return nativeGetUidStat(uid, TYPE_RX_BYTES);
+        } else {
+            return UNSUPPORTED;
+        }
     }
 
     /**
@@ -531,12 +562,25 @@
      * <p>
      * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
      * {@link #UNSUPPORTED} on devices where statistics aren't available.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
+     * report traffic statistics for the calling UID. It will return
+     * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
+     * historical network statistics belonging to other UIDs, use
+     * {@link NetworkStatsManager}.
      *
      * @see android.os.Process#myUid()
      * @see android.content.pm.ApplicationInfo#uid
      */
     public static long getUidTxPackets(int uid) {
-        return nativeGetUidStat(uid, TYPE_TX_PACKETS);
+        // This isn't actually enforcing any security; it just returns the
+        // unsupported value. The real filtering is done at the kernel level.
+        final int callingUid = android.os.Process.myUid();
+        if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
+            return nativeGetUidStat(uid, TYPE_TX_PACKETS);
+        } else {
+            return UNSUPPORTED;
+        }
     }
 
     /**
@@ -547,12 +591,25 @@
      * <p>
      * Before {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, this may return
      * {@link #UNSUPPORTED} on devices where statistics aren't available.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#N} this will only
+     * report traffic statistics for the calling UID. It will return
+     * {@link #UNSUPPORTED} for all other UIDs for privacy reasons. To access
+     * historical network statistics belonging to other UIDs, use
+     * {@link NetworkStatsManager}.
      *
      * @see android.os.Process#myUid()
      * @see android.content.pm.ApplicationInfo#uid
      */
     public static long getUidRxPackets(int uid) {
-        return nativeGetUidStat(uid, TYPE_RX_PACKETS);
+        // This isn't actually enforcing any security; it just returns the
+        // unsupported value. The real filtering is done at the kernel level.
+        final int callingUid = android.os.Process.myUid();
+        if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) {
+            return nativeGetUidStat(uid, TYPE_RX_PACKETS);
+        } else {
+            return UNSUPPORTED;
+        }
     }
 
     /**
diff --git a/core/java/android/os/BadParcelableException.java b/core/java/android/os/BadParcelableException.java
index a1c5bb2..7e0b1a5 100644
--- a/core/java/android/os/BadParcelableException.java
+++ b/core/java/android/os/BadParcelableException.java
@@ -15,11 +15,15 @@
  */
 
 package android.os;
+
 import android.util.AndroidRuntimeException;
 
 /**
- * The object you are calling has died, because its hosting process
- * no longer exists.
+ * Exception thrown when a {@link Parcelable} is malformed or otherwise invalid.
+ * <p>
+ * This is typically encountered when a custom {@link Parcelable} object is
+ * passed to another process that doesn't have the same {@link Parcelable} class
+ * in its {@link ClassLoader}.
  */
 public class BadParcelableException extends AndroidRuntimeException {
     public BadParcelableException(String msg) {
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 5c71373..6e50155 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -26,7 +26,9 @@
 import java.util.Set;
 
 /**
- * A mapping from String values to various types.
+ * A mapping from String keys to values of various types. In most cases, you
+ * should work directly with either the {@link Bundle} or
+ * {@link PersistableBundle} subclass.
  */
 public class BaseBundle {
     private static final String TAG = "Bundle";
@@ -35,6 +37,32 @@
     // Keep in sync with frameworks/native/libs/binder/PersistableBundle.cpp.
     static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
 
+    /**
+     * Flag indicating that this Bundle is okay to "defuse." That is, it's okay
+     * for system processes to ignore any {@link BadParcelableException}
+     * encountered when unparceling it, leaving an empty bundle in its place.
+     * <p>
+     * This should <em>only</em> be set when the Bundle reaches its final
+     * destination, otherwise a system process may clobber contents that were
+     * destined for an app that could have unparceled them.
+     */
+    static final int FLAG_DEFUSABLE = 1 << 0;
+
+    private static volatile boolean sShouldDefuse = false;
+
+    /**
+     * Set global variable indicating that any Bundles parsed in this process
+     * should be "defused." That is, any {@link BadParcelableException}
+     * encountered will be suppressed and logged, leaving an empty Bundle
+     * instead of crashing.
+     *
+     * @hide
+     */
+    public static void setShouldDefuse(boolean shouldDefuse) {
+        sShouldDefuse = shouldDefuse;
+    }
+
+    /** {@hide} */
     static final Parcel EMPTY_PARCEL;
 
     static {
@@ -58,6 +86,9 @@
      */
     private ClassLoader mClassLoader;
 
+    /** {@hide} */
+    int mFlags;
+
     /**
      * Constructs a new, empty Bundle that uses a specific ClassLoader for
      * instantiating Parcelable and Serializable objects.
@@ -197,6 +228,11 @@
             return;
         }
 
+        if (sShouldDefuse && (mFlags & FLAG_DEFUSABLE) == 0) {
+            Log.wtf(TAG, "Attempting to unparcel a Bundle while in transit; this may "
+                    + "clobber all data inside!", new Throwable());
+        }
+
         if (mParcelledData == EMPTY_PARCEL) {
             if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
                     + ": empty");
@@ -221,9 +257,19 @@
             mMap.erase();
             mMap.ensureCapacity(N);
         }
-        mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
-        mParcelledData.recycle();
-        mParcelledData = null;
+        try {
+            mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
+        } catch (BadParcelableException e) {
+            if (sShouldDefuse) {
+                Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
+                mMap.erase();
+            } else {
+                throw e;
+            }
+        } finally {
+            mParcelledData.recycle();
+            mParcelledData = null;
+        }
         if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
                 + " final map: " + mMap);
     }
@@ -1371,9 +1417,8 @@
             return;
         }
 
-        int magic = parcel.readInt();
+        final int magic = parcel.readInt();
         if (magic != BUNDLE_MAGIC) {
-            //noinspection ThrowableInstanceNeverThrown
             throw new IllegalStateException("Bad magic number for Bundle: 0x"
                     + Integer.toHexString(magic));
         }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 8281279..e1c7ad77 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -465,6 +465,7 @@
         };
 
         public abstract long getProcessStateTime(int state, long elapsedRealtimeUs, int which);
+        public abstract Timer getProcessStateTimer(int state);
 
         public abstract Timer getVibratorOnTimer();
 
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index d73deb6..ea8ba2f 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -70,6 +70,9 @@
     private static final boolean CHECK_PARCEL_SIZE = false;
     static final String TAG = "Binder";
 
+    /** @hide */
+    public static boolean LOG_RUNTIME_EXCEPTION = false; // DO NOT SUBMIT WITH TRUE
+
     /**
      * Control whether dump() calls are allowed.
      */
@@ -560,17 +563,16 @@
         // If the call was FLAG_ONEWAY then these exceptions disappear into the ether.
         try {
             res = onTransact(code, data, reply, flags);
-        } catch (RemoteException e) {
-            if ((flags & FLAG_ONEWAY) != 0) {
-                Log.w(TAG, "Binder call failed.", e);
-            } else {
-                reply.setDataPosition(0);
-                reply.writeException(e);
-            }
-            res = true;
-        } catch (RuntimeException e) {
-            if ((flags & FLAG_ONEWAY) != 0) {
+        } catch (RemoteException|RuntimeException e) {
+            if (LOG_RUNTIME_EXCEPTION) {
                 Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
+            }
+            if ((flags & FLAG_ONEWAY) != 0) {
+                if (e instanceof RemoteException) {
+                    Log.w(TAG, "Binder call failed.", e);
+                } else {
+                    Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
+                }
             } else {
                 reply.setDataPosition(0);
                 reply.writeException(e);
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 74699fd..1097cad 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -27,11 +27,17 @@
 import java.util.List;
 
 /**
- * A mapping from String values to various Parcelable types.
+ * A mapping from String keys to various {@link Parcelable} values.
  *
+ * @see PersistableBundle
  */
 public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
+    private static final int FLAG_HAS_FDS = 1 << 8;
+    private static final int FLAG_HAS_FDS_KNOWN = 1 << 9;
+    private static final int FLAG_ALLOW_FDS = 1 << 10;
+
     public static final Bundle EMPTY;
+
     static final Parcel EMPTY_PARCEL;
 
     static {
@@ -40,15 +46,12 @@
         EMPTY_PARCEL = BaseBundle.EMPTY_PARCEL;
     }
 
-    private boolean mHasFds = false;
-    private boolean mFdsKnown = true;
-    private boolean mAllowFds = true;
-
     /**
      * Constructs a new, empty Bundle.
      */
     public Bundle() {
         super();
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -59,16 +62,18 @@
      */
     Bundle(Parcel parcelledData) {
         super(parcelledData);
-
-        mHasFds = mParcelledData.hasFileDescriptors();
-        mFdsKnown = true;
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
+        if (mParcelledData.hasFileDescriptors()) {
+            mFlags |= FLAG_HAS_FDS;
+        }
     }
 
     /* package */ Bundle(Parcel parcelledData, int length) {
         super(parcelledData, length);
-
-        mHasFds = mParcelledData.hasFileDescriptors();
-        mFdsKnown = true;
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
+        if (mParcelledData.hasFileDescriptors()) {
+            mFlags |= FLAG_HAS_FDS;
+        }
     }
 
     /**
@@ -80,6 +85,7 @@
      */
     public Bundle(ClassLoader loader) {
         super(loader);
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -90,6 +96,7 @@
      */
     public Bundle(int capacity) {
         super(capacity);
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -100,9 +107,7 @@
      */
     public Bundle(Bundle b) {
         super(b);
-
-        mHasFds = b.mHasFds;
-        mFdsKnown = b.mFdsKnown;
+        mFlags = b.mFlags;
     }
 
     /**
@@ -113,6 +118,7 @@
      */
     public Bundle(PersistableBundle b) {
         super(b);
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -145,14 +151,37 @@
         return super.getClassLoader();
     }
 
-    /** @hide */
+    /** {@hide} */
     public boolean setAllowFds(boolean allowFds) {
-        boolean orig = mAllowFds;
-        mAllowFds = allowFds;
+        final boolean orig = (mFlags & FLAG_ALLOW_FDS) != 0;
+        if (allowFds) {
+            mFlags |= FLAG_ALLOW_FDS;
+        } else {
+            mFlags &= ~FLAG_ALLOW_FDS;
+        }
         return orig;
     }
 
     /**
+     * Mark if this Bundle is okay to "defuse." That is, it's okay for system
+     * processes to ignore any {@link BadParcelableException} encountered when
+     * unparceling it, leaving an empty bundle in its place.
+     * <p>
+     * This should <em>only</em> be set when the Bundle reaches its final
+     * destination, otherwise a system process may clobber contents that were
+     * destined for an app that could have unparceled them.
+     *
+     * @hide
+     */
+    public void setDefusable(boolean defusable) {
+        if (defusable) {
+            mFlags |= FLAG_DEFUSABLE;
+        } else {
+            mFlags &= ~FLAG_DEFUSABLE;
+        }
+    }
+
+    /**
      * Clones the current Bundle. The internal map is cloned, but the keys and
      * values to which it refers are copied by reference.
      */
@@ -167,9 +196,7 @@
     @Override
     public void clear() {
         super.clear();
-
-        mHasFds = false;
-        mFdsKnown = true;
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
     }
 
     /**
@@ -182,16 +209,20 @@
         bundle.unparcel();
         mMap.putAll(bundle.mMap);
 
-        // fd state is now known if and only if both bundles already knew
-        mHasFds |= bundle.mHasFds;
-        mFdsKnown = mFdsKnown && bundle.mFdsKnown;
+        // FD state is now known if and only if both bundles already knew
+        if ((bundle.mFlags & FLAG_HAS_FDS) != 0) {
+            mFlags |= FLAG_HAS_FDS;
+        }
+        if ((bundle.mFlags & FLAG_HAS_FDS_KNOWN) == 0) {
+            mFlags &= ~FLAG_HAS_FDS_KNOWN;
+        }
     }
 
     /**
      * Reports whether the bundle contains any parcelled file descriptors.
      */
     public boolean hasFileDescriptors() {
-        if (!mFdsKnown) {
+        if ((mFlags & FLAG_HAS_FDS_KNOWN) == 0) {
             boolean fdFound = false;    // keep going until we find one or run out of data
 
             if (mParcelledData != null) {
@@ -247,10 +278,12 @@
                 }
             }
 
-            mHasFds = fdFound;
-            mFdsKnown = true;
+            if (fdFound) {
+                mFlags |= FLAG_HAS_FDS;
+            }
+            mFlags |= FLAG_HAS_FDS_KNOWN;
         }
-        return mHasFds;
+        return (mFlags & FLAG_HAS_FDS) != 0;
     }
 
     /**
@@ -346,7 +379,7 @@
     public void putParcelable(@Nullable String key, @Nullable Parcelable value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /**
@@ -384,7 +417,7 @@
     public void putParcelableArray(@Nullable String key, @Nullable Parcelable[] value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /**
@@ -399,14 +432,14 @@
             @Nullable ArrayList<? extends Parcelable> value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /** {@hide} */
     public void putParcelableList(String key, List<? extends Parcelable> value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /**
@@ -421,7 +454,7 @@
             @Nullable SparseArray<? extends Parcelable> value) {
         unparcel();
         mMap.put(key, value);
-        mFdsKnown = false;
+        mFlags &= ~FLAG_HAS_FDS_KNOWN;
     }
 
     /**
@@ -1074,7 +1107,7 @@
      */
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
-        final boolean oldAllowFds = parcel.pushAllowFds(mAllowFds);
+        final boolean oldAllowFds = parcel.pushAllowFds((mFlags & FLAG_ALLOW_FDS) != 0);
         try {
             super.writeToParcelInner(parcel, flags);
         } finally {
@@ -1089,8 +1122,10 @@
      */
     public void readFromParcel(Parcel parcel) {
         super.readFromParcelInner(parcel);
-        mHasFds = mParcelledData.hasFileDescriptors();
-        mFdsKnown = true;
+        mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
+        if (mParcelledData.hasFileDescriptors()) {
+            mFlags |= FLAG_HAS_FDS;
+        }
     }
 
     @Override
@@ -1105,5 +1140,4 @@
         }
         return "Bundle[" + mMap.toString() + "]";
     }
-
 }
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index 0d94072..cb85eef 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -16,6 +16,9 @@
 
 package android.os;
 
+import android.content.Context;
+import android.util.Log;
+
 import com.android.internal.os.IDropBoxManagerService;
 
 import java.io.ByteArrayInputStream;
@@ -40,6 +43,8 @@
  */
 public class DropBoxManager {
     private static final String TAG = "DropBoxManager";
+
+    private final Context mContext;
     private final IDropBoxManagerService mService;
 
     /** Flag value: Entry's content was deleted to save space. */
@@ -249,14 +254,20 @@
     }
 
     /** {@hide} */
-    public DropBoxManager(IDropBoxManagerService service) { mService = service; }
+    public DropBoxManager(Context context, IDropBoxManagerService service) {
+        mContext = context;
+        mService = service;
+    }
 
     /**
      * Create a dummy instance for testing.  All methods will fail unless
      * overridden with an appropriate mock implementation.  To obtain a
      * functional instance, use {@link android.content.Context#getSystemService}.
      */
-    protected DropBoxManager() { mService = null; }
+    protected DropBoxManager() {
+        mContext = null;
+        mService = null;
+    }
 
     /**
      * Stores human-readable text.  The data may be discarded eventually (or even
@@ -270,6 +281,11 @@
         try {
             mService.add(new Entry(tag, 0, data));
         } catch (RemoteException e) {
+            if (e instanceof TransactionTooLargeException
+                    && mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
+                Log.e(TAG, "App sent too much data, so it was ignored", e);
+                return;
+            }
             throw e.rethrowFromSystemServer();
         }
     }
@@ -286,6 +302,11 @@
         try {
             mService.add(new Entry(tag, 0, data, flags));
         } catch (RemoteException e) {
+            if (e instanceof TransactionTooLargeException
+                    && mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
+                Log.e(TAG, "App sent too much data, so it was ignored", e);
+                return;
+            }
             throw e.rethrowFromSystemServer();
         }
     }
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 1b79497..dd73e53 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -605,6 +605,30 @@
      */
     public static File buildUniqueFile(File parent, String mimeType, String displayName)
             throws FileNotFoundException {
+        final String[] parts = splitFileName(mimeType, displayName);
+        final String name = parts[0];
+        final String ext = parts[1];
+        File file = buildFile(parent, name, ext);
+
+        // If conflicting file, try adding counter suffix
+        int n = 0;
+        while (file.exists()) {
+            if (n++ >= 32) {
+                throw new FileNotFoundException("Failed to create unique file");
+            }
+            file = buildFile(parent, name + " (" + n + ")", ext);
+        }
+
+        return file;
+    }
+
+    /**
+     * Splits file name into base name and extension.
+     * If the display name doesn't have an extension that matches the requested MIME type, the
+     * extension is regarded as a part of filename and default extension for that MIME type is
+     * appended.
+     */
+    public static String[] splitFileName(String mimeType, String displayName) {
         String name;
         String ext;
 
@@ -642,18 +666,11 @@
             }
         }
 
-        File file = buildFile(parent, name, ext);
-
-        // If conflicting file, try adding counter suffix
-        int n = 0;
-        while (file.exists()) {
-            if (n++ >= 32) {
-                throw new FileNotFoundException("Failed to create unique file");
-            }
-            file = buildFile(parent, name + " (" + n + ")", ext);
+        if (ext == null) {
+            ext = "";
         }
 
-        return file;
+        return new String[] { name, ext };
     }
 
     private static File buildFile(File parent, String name, String ext) {
diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl
index 838279b..082194b 100644
--- a/core/java/android/os/IDeviceIdleController.aidl
+++ b/core/java/android/os/IDeviceIdleController.aidl
@@ -25,10 +25,12 @@
     void removePowerSaveWhitelistApp(String name);
     String[] getSystemPowerWhitelistExceptIdle();
     String[] getSystemPowerWhitelist();
+    String[] getUserPowerWhitelist();
     String[] getFullPowerWhitelistExceptIdle();
     String[] getFullPowerWhitelist();
     int[] getAppIdWhitelistExceptIdle();
     int[] getAppIdWhitelist();
+    int[] getAppIdUserWhitelist();
     int[] getAppIdTempWhitelist();
     boolean isPowerSaveWhitelistExceptIdleApp(String name);
     boolean isPowerSaveWhitelistApp(String name);
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index f36bb29..b947c97 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -18,7 +18,9 @@
 
 import android.annotation.Nullable;
 import android.util.ArrayMap;
+
 import com.android.internal.util.XmlUtils;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -26,9 +28,11 @@
 import java.io.IOException;
 
 /**
- * A mapping from String values to various types that can be saved to persistent and later
- * restored.
+ * A mapping from String keys to values of various types. The set of types
+ * supported by this class is purposefully restricted to simple objects that can
+ * safely be persisted to and restored from disk.
  *
+ * @see Bundle
  */
 public final class PersistableBundle extends BaseBundle implements Cloneable, Parcelable,
         XmlUtils.WriteMapCallback {
@@ -57,6 +61,7 @@
      */
     public PersistableBundle() {
         super();
+        mFlags = FLAG_DEFUSABLE;
     }
 
     /**
@@ -67,6 +72,7 @@
      */
     public PersistableBundle(int capacity) {
         super(capacity);
+        mFlags = FLAG_DEFUSABLE;
     }
 
     /**
@@ -77,6 +83,7 @@
      */
     public PersistableBundle(PersistableBundle b) {
         super(b);
+        mFlags = b.mFlags;
     }
 
 
@@ -86,6 +93,8 @@
      * @param b a Bundle to be copied.
      *
      * @throws IllegalArgumentException if any element of {@code b} cannot be persisted.
+     *
+     * @hide
      */
     public PersistableBundle(Bundle b) {
         this(b.getMap());
@@ -99,6 +108,7 @@
      */
     private PersistableBundle(ArrayMap<String, Object> map) {
         super();
+        mFlags = FLAG_DEFUSABLE;
 
         // First stuff everything in.
         putAll(map);
@@ -121,6 +131,7 @@
 
     /* package */ PersistableBundle(Parcel parcelledData, int length) {
         super(parcelledData, length);
+        mFlags = FLAG_DEFUSABLE;
     }
 
     /**
@@ -276,5 +287,4 @@
         }
         return "PersistableBundle[" + mMap.toString() + "]";
     }
-
 }
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index ddcd635..b25b33d 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -434,25 +434,35 @@
             String filename = packageFile.getCanonicalPath();
             Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
 
-            if (!processed && filename.startsWith("/data/")) {
-                FileWriter uncryptFile = new FileWriter(UNCRYPT_PACKAGE_FILE);
-                try {
-                    uncryptFile.write(filename + "\n");
-                } finally {
-                    uncryptFile.close();
-                }
-                // UNCRYPT_PACKAGE_FILE needs to be readable and writable by system server.
-                if (!UNCRYPT_PACKAGE_FILE.setReadable(true, false)
-                        || !UNCRYPT_PACKAGE_FILE.setWritable(true, false)) {
-                    Log.e(TAG, "Error setting permission for " + UNCRYPT_PACKAGE_FILE);
-                }
-
-                BLOCK_MAP_FILE.delete();
-            }
-
-            // If the package is on the /data partition, use the block map file as
-            // the package name instead.
+            // If the package is on the /data partition, the package needs to
+            // be processed (i.e. uncrypt'd). The caller specifies if that has
+            // been done in 'processed' parameter.
             if (filename.startsWith("/data/")) {
+                if (processed) {
+                    if (!BLOCK_MAP_FILE.exists()) {
+                        Log.e(TAG, "Package claimed to have been processed but failed to find "
+                                + "the block map file.");
+                        throw new IOException("Failed to find block map file");
+                    }
+                } else {
+                    FileWriter uncryptFile = new FileWriter(UNCRYPT_PACKAGE_FILE);
+                    try {
+                        uncryptFile.write(filename + "\n");
+                    } finally {
+                        uncryptFile.close();
+                    }
+                    // UNCRYPT_PACKAGE_FILE needs to be readable and writable
+                    // by system server.
+                    if (!UNCRYPT_PACKAGE_FILE.setReadable(true, false)
+                            || !UNCRYPT_PACKAGE_FILE.setWritable(true, false)) {
+                        Log.e(TAG, "Error setting permission for " + UNCRYPT_PACKAGE_FILE);
+                    }
+
+                    BLOCK_MAP_FILE.delete();
+                }
+
+                // If the package is on the /data partition, use the block map
+                // file as the package name instead.
                 filename = "@/cache/recovery/block.map";
             }
 
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 7223dfb..e2675b1 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -972,7 +972,8 @@
 
     /**
      * Returns the UserInfo object describing a specific user.
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission or the caller is
+     * in the same profile group of target user.
      * @param userHandle the user handle of the user whose information is being requested.
      * @return the UserInfo object for a specific user.
      * @hide
diff --git a/core/java/android/os/health/HealthKeys.java b/core/java/android/os/health/HealthKeys.java
new file mode 100644
index 0000000..842def3
--- /dev/null
+++ b/core/java/android/os/health/HealthKeys.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2016 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.health;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+
+/**
+ * Constants and stuff for the android.os.health package.
+ *
+ * @hide
+ */
+public class HealthKeys {
+
+    /**
+     * No valid key will ever be 0.
+     */
+    public static final int UNKNOWN_KEY = 0;
+
+    /*
+     * Base key for each of the different classes. There is
+     * nothing intrinsic to the operation of the value of the
+     * keys. It's just segmented for better debugging. The
+     * classes don't mix them anway.
+     */
+    public static final int BASE_UID = 10000;
+    public static final int BASE_PID = 20000;
+    public static final int BASE_PROCESS = 30000;
+    public static final int BASE_PACKAGE = 40000;
+    public static final int BASE_SERVICE = 50000;
+
+    /*
+     * The types of values supported by HealthStats.
+     */
+    public static final int TYPE_TIMER = 0;
+    public static final int TYPE_MEASUREMENT = 1;
+    public static final int TYPE_STATS = 2;
+    public static final int TYPE_TIMERS = 3;
+    public static final int TYPE_MEASUREMENTS = 4;
+
+    public static final int TYPE_COUNT = 5;
+
+    /**
+     * Annotation to mark public static final int fields that are to be used
+     * as field keys in HealthStats.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD})
+    public @interface Constant {
+        /**
+         * One of the TYPE_* constants above.
+         */
+        int type();
+    }
+
+    /**
+     * Class to gather the constants defined in a class full of constants and
+     * build the key indices used by HealthStatsWriter and HealthStats.
+     *
+     * @hide
+     */
+    public static class Constants {
+        private final String mDataType;
+        private final int[][] mKeys = new int[TYPE_COUNT][];
+
+        /**
+         * Pass in a class to gather the public static final int fields that are
+         * tagged with the @Constant annotation.
+         */
+        public Constants(Class clazz) {
+            // Save the class name for debugging
+            mDataType = clazz.getSimpleName();
+
+            // Iterate through the list of fields on this class, and build the
+            // constant arrays for these fields.
+            final Field[] fields = clazz.getDeclaredFields();
+            final Class<Constant> annotationClass = Constant.class;
+
+            final int N = fields.length;
+
+            final SortedIntArray[] keys = new SortedIntArray[mKeys.length];
+            for (int i=0; i<keys.length; i++) {
+                keys[i] = new SortedIntArray(N);
+            }
+
+            for (int i=0; i<N; i++) {
+                final Field field = fields[i];
+                final Constant constant = field.getAnnotation(annotationClass);
+                if (constant != null) {
+                    final int type = constant.type();
+                    if (type >= keys.length) {
+                        throw new RuntimeException("Unknown Constant type " + type
+                                + " on " + field);
+                    }
+                    try {
+                        keys[type].addValue(field.getInt(null));
+                    } catch (IllegalAccessException ex) {
+                        throw new RuntimeException("Can't read constant value type=" + type
+                                + " field=" + field, ex);
+                    }
+                }
+            }
+
+            for (int i=0; i<keys.length; i++) {
+                mKeys[i] = keys[i].getArray();
+            }
+        }
+
+        /**
+         * Get a string representation of this class. Useful for debugging. It will be the
+         * simple name of the class passed in the constructor.
+         */
+        public String getDataType() {
+            return mDataType;
+        }
+
+        /**
+         * Return how many keys there are for the given field type.
+         *
+         * @see TYPE_TIMER
+         * @see TYPE_MEASUREMENT
+         * @see TYPE_TIMERS
+         * @see TYPE_MEASUREMENTS
+         * @see TYPE_STATS
+         */
+        public int getSize(int type) {
+            return mKeys[type].length;
+        }
+
+        /**
+         * Return the index for the given type and key combination in the array of field
+         * keys or values.
+         *
+         * @see TYPE_TIMER
+         * @see TYPE_MEASUREMENT
+         * @see TYPE_TIMERS
+         * @see TYPE_MEASUREMENTS
+         * @see TYPE_STATS
+         */
+        public int getIndex(int type, int key) {
+            final int index = Arrays.binarySearch(mKeys[type], key);
+            if (index >= 0) {
+                return index;
+            } else {
+                throw new RuntimeException("Unknown Constant " + key + " (of type "
+                        + type + " )");
+            }
+        }
+
+        /**
+         * Get the array of keys for the given field type.
+         */
+        public int[] getKeys(int type) {
+            return mKeys[type];
+        }
+    }
+
+    /**
+     * An array of fixed size that will be sorted.
+     */
+    private static class SortedIntArray {
+        int mCount;
+        int[] mArray;
+
+        /**
+         * Construct with the maximum number of values.
+         */
+        SortedIntArray(int maxCount) {
+            mArray = new int[maxCount];
+        }
+
+        /**
+         * Add a value.
+         */
+        void addValue(int value) {
+            mArray[mCount++] = value;
+        }
+
+        /**
+         * Get the array of values that have been added, with the values in
+         * numerically increasing order.
+         */
+        int[] getArray() {
+            if (mCount == mArray.length) {
+                Arrays.sort(mArray);
+                return mArray;
+            } else {
+                final int[] result = new int[mCount];
+                System.arraycopy(mArray, 0, result, 0, mCount);
+                Arrays.sort(result);
+                return result;
+            }
+        }
+    }
+}
+
+
diff --git a/core/java/android/os/health/HealthStats.java b/core/java/android/os/health/HealthStats.java
new file mode 100644
index 0000000..f0489e2
--- /dev/null
+++ b/core/java/android/os/health/HealthStats.java
@@ -0,0 +1,481 @@
+/*
+ * Copyright (C) 2016 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.health;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * A HealthStats object contains system health data about an application.
+ *
+ * <p>
+ * <b>Data Types</b><br>
+ * Each of the keys references data in one of five data types:
+ *
+ * <p>
+ * A <b>measurement</b> metric contains a sinlge {@code long} value. That value may
+ * be a count, a time, or some other type of value. The unit for a measurement
+ * (COUNT, MS, etc) will always be in the name of the constant for the key to
+ * retrieve it. For example, the
+ * {@link android.os.health.UidHealthStats#MEASUREMENT_WIFI_TX_MS UidHealthStats.MEASUREMENT_WIFI_TX_MS}
+ * value is the number of milliseconds (ms) that were spent transmitting on wifi by an
+ * application.  The
+ * {@link android.os.health.UidHealthStats#MEASUREMENT_MOBILE_RX_PACKETS UidHealthStats.MEASUREMENT_MOBILE_RX_PACKETS}
+ * measurement is the number of packets received on behalf of an application.
+ * The {@link android.os.health.UidHealthStats#MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT
+ *     UidHealthStats.MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT}
+ * measurement is the number of times the user touched the screen, causing the
+ * screen to stay awake.
+ *
+ *
+ * <p>
+ * A <b>timer</b> metric contains an {@code int} count and a {@code long} time,
+ * measured in milliseconds. Timers track how many times a resource was used, and
+ * the total duration for that usage. For example, the
+ * {@link android.os.health.UidHealthStats#TIMER_FLASHLIGHT}
+ * timer tracks how many times the application turned on the flashlight, and for
+ * how many milliseconds total it kept it on.
+ *
+ * <p>
+ * A <b>measurement map</b> metric is a mapping of {@link java.lang.String} names to
+ * {@link java.lang.Long} values.  The names typically are application provided names. For
+ * example, the
+ * {@link android.os.health.PackageHealthStats#MEASUREMENTS_WAKEUP_ALARMS_COUNT
+ *         PackageHealthStats.MEASUREMENTS_WAKEUP_ALARMS_COUNT}
+ * measurement map is a mapping of the tag provided to the
+ * {@link android.app.AlarmManager} when the alarm is scheduled.
+ *
+ * <p>
+ * A <b>timer map</b> metric is a mapping of {@link java.lang.String} names to
+ * {@link android.os.health.TimerStat} objects. The names are typically application
+ * provided names.  For example, the
+ * {@link android.os.health.UidHealthStats#TIMERS_WAKELOCKS_PARTIAL UidHealthStats.TIMERS_WAKELOCKS_PARTIAL}
+ * is a mapping of tag provided to the {@link android.os.PowerManager} when the
+ * wakelock is created to the number of times and for how long each wakelock was
+ * active.
+ *
+ * <p>
+ * Lastly, a <b>health stats</b> metric is a mapping of {@link java.lang.String}
+ * names to a recursive {@link android.os.health.HealthStats} object containing
+ * more detailed information. For example, the
+ * {@link android.os.health.UidHealthStats#STATS_PACKAGES UidHealthStats.STATS_PACKAGES}
+ * metric is a mapping of the package names for each of the APKs sharing a uid to
+ * the information recorded for that apk.  The returned HealthStats objects will
+ * each be associated with a different set of constants.  For the HealthStats
+ * returned for UidHealthStats.STATS_PACKAGES, the keys come from the
+ * {@link android.os.health.PackageHealthStats}  class.
+ *
+ */
+public class HealthStats {
+    // Header fields
+    private String mDataType;
+
+    // TimerStat fields
+    private int[] mTimerKeys;
+    private int[] mTimerCounts;
+    private long[] mTimerTimes;
+
+    // Measurement fields
+    private int[] mMeasurementKeys;
+    private long[] mMeasurementValues;
+
+    // Stats fields
+    private int[] mStatsKeys;
+    private ArrayMap<String,HealthStats>[] mStatsValues;
+
+    // Timers fields
+    private int[] mTimersKeys;
+    private ArrayMap<String,TimerStat>[] mTimersValues;
+
+    // Measurements fields
+    private int[] mMeasurementsKeys;
+    private ArrayMap<String,Long>[] mMeasurementsValues;
+
+    /**
+     * HealthStats empty constructor not implemented because this
+     * class is read-only.
+     */
+    private HealthStats() {
+        throw new RuntimeException("unsupported");
+    }
+
+    /**
+     * Construct a health stats object from a parcel.
+     *
+     * @hide
+     */
+    public HealthStats(Parcel in) {
+        int count;
+
+        // Header fields
+        mDataType = in.readString();
+
+        // TimerStat fields
+        count = in.readInt();
+        mTimerKeys = new int[count];
+        mTimerCounts = new int[count];
+        mTimerTimes = new long[count];
+        for (int i=0; i<count; i++) {
+            mTimerKeys[i] = in.readInt();
+            mTimerCounts[i] = in.readInt();
+            mTimerTimes[i] = in.readLong();
+        }
+
+        // Measurement fields
+        count = in.readInt();
+        mMeasurementKeys = new int[count];
+        mMeasurementValues = new long[count];
+        for (int i=0; i<count; i++) {
+            mMeasurementKeys[i] = in.readInt();
+            mMeasurementValues[i] = in.readLong();
+        }
+
+        // Stats fields
+        count = in.readInt();
+        mStatsKeys = new int[count];
+        mStatsValues = new ArrayMap[count];
+        for (int i=0; i<count; i++) {
+            mStatsKeys[i] = in.readInt();
+            mStatsValues[i] = createHealthStatsMap(in);
+        }
+
+        // Timers fields
+        count = in.readInt();
+        mTimersKeys = new int[count];
+        mTimersValues = new ArrayMap[count];
+        for (int i=0; i<count; i++) {
+            mTimersKeys[i] = in.readInt();
+            mTimersValues[i] = createParcelableMap(in, TimerStat.CREATOR);
+        }
+
+        // Measurements fields
+        count = in.readInt();
+        mMeasurementsKeys = new int[count];
+        mMeasurementsValues = new ArrayMap[count];
+        for (int i=0; i<count; i++) {
+            mMeasurementsKeys[i] = in.readInt();
+            mMeasurementsValues[i] = createLongsMap(in);
+        }
+    }
+
+    /**
+     * Get a name representing the contents of this object.
+     *
+     * @see UidHealthStats
+     * @see PackageHealthStats
+     * @see PidHealthStats
+     * @see ProcessHealthStats
+     * @see ServiceHealthStats
+     */
+    public String getDataType() {
+        return mDataType;
+    }
+
+    /**
+     * Return whether this object contains a TimerStat for the supplied key.
+     */
+    public boolean hasTimer(int key) {
+        return getIndex(mTimerKeys, key) >= 0;
+    }
+
+    /**
+     * Return a TimerStat object for the given key.
+     *
+     * This will allocate a new {@link TimerStat} object, which may be wasteful. Instead, use
+     * {@link #getTimerCount} and {@link #getTimerTime}.
+     *
+     * @throws IndexOutOfBoundsException When the key is not present in this object.
+     * @see #hasTimer hasTimer(int) To check if a value for the given key is present.
+     */
+    public TimerStat getTimer(int key) {
+        final int index = getIndex(mTimerKeys, key);
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Bad timer key dataType=" + mDataType
+                    + " key=" + key);
+        }
+        return new TimerStat(mTimerCounts[index], mTimerTimes[index]);
+    }
+
+    /**
+     * Get the count for the timer for the given key.
+     *
+     * @throws IndexOutOfBoundsException When the key is not present in this object.
+     * @see #hasTimer hasTimer(int) To check if a value for the given key is present.
+     */
+    public int getTimerCount(int key) {
+        final int index = getIndex(mTimerKeys, key);
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Bad timer key dataType=" + mDataType
+                    + " key=" + key);
+        }
+        return mTimerCounts[index];
+    }
+
+    /**
+     * Get the time for the timer for the given key, in milliseconds.
+     *
+     * @throws IndexOutOfBoundsException When the key is not present in this object.
+     * @see #hasTimer hasTimer(int) To check if a value for the given key is present.
+     */
+    public long getTimerTime(int key) {
+        final int index = getIndex(mTimerKeys, key);
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Bad timer key dataType=" + mDataType
+                    + " key=" + key);
+        }
+        return mTimerTimes[index];
+    }
+
+    /**
+     * Get the number of timer values in this object. Can be used to iterate through
+     * the available timers.
+     *
+     * @see #getTimerKeyAt
+     */
+    public int getTimerKeyCount() {
+        return mTimerKeys.length;
+    }
+
+    /**
+     * Get the key for the timer at the given index.  Index must be between 0 and the result
+     * of {@link #getTimerKeyCount getTimerKeyCount()}.
+     *
+     * @see #getTimerKeyCount
+     */
+    public int getTimerKeyAt(int index) {
+        return mTimerKeys[index];
+    }
+
+    /**
+     * Return whether this object contains a measurement for the supplied key.
+     */
+    public boolean hasMeasurement(int key) {
+        return getIndex(mMeasurementKeys, key) >= 0;
+    }
+
+    /**
+     * Get the measurement for the given key.
+     *
+     * @throws IndexOutOfBoundsException When the key is not present in this object.
+     * @see #hasMeasurement hasMeasurement(int) To check if a value for the given key is present.
+     */
+    public long getMeasurement(int key) {
+        final int index = getIndex(mMeasurementKeys, key);
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Bad measurement key dataType=" + mDataType
+                    + " key=" + key);
+        }
+        return mMeasurementValues[index];
+    }
+
+    /**
+     * Get the number of measurement values in this object. Can be used to iterate through
+     * the available measurements.
+     *
+     * @see #getMeasurementKeyAt
+     */
+    public int getMeasurementKeyCount() {
+        return mMeasurementKeys.length;
+    }
+
+    /**
+     * Get the key for the measurement at the given index.  Index must be between 0 and the result
+     * of {@link #getMeasurementKeyCount getMeasurementKeyCount()}.
+     *
+     * @see #getMeasurementKeyCount
+     */
+    public int getMeasurementKeyAt(int index) {
+        return mMeasurementKeys[index];
+    }
+
+    /**
+     * Return whether this object contains a HealthStats map for the supplied key.
+     */
+    public boolean hasStats(int key) {
+        return getIndex(mStatsKeys, key) >= 0;
+    }
+
+    /**
+     * Get the HealthStats map for the given key.
+     *
+     * @throws IndexOutOfBoundsException When the key is not present in this object.
+     * @see #hasStats hasStats(int) To check if a value for the given key is present.
+     */
+    public Map<String,HealthStats> getStats(int key) {
+        final int index = getIndex(mStatsKeys, key);
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Bad stats key dataType=" + mDataType
+                    + " key=" + key);
+        }
+        return mStatsValues[index];
+    }
+
+    /**
+     * Get the number of HealthStat map values in this object. Can be used to iterate through
+     * the available measurements.
+     *
+     * @see #getMeasurementKeyAt
+     */
+    public int getStatsKeyCount() {
+        return mStatsKeys.length;
+    }
+
+    /**
+     * Get the key for the timer at the given index.  Index must be between 0 and the result
+     * of {@link #getStatsKeyCount getStatsKeyCount()}.
+     *
+     * @see #getStatsKeyCount
+     */
+    public int getStatsKeyAt(int index) {
+        return mStatsKeys[index];
+    }
+
+    /**
+     * Return whether this object contains a timers map for the supplied key.
+     */
+    public boolean hasTimers(int key) {
+        return getIndex(mTimersKeys, key) >= 0;
+    }
+
+    /**
+     * Get the TimerStat map for the given key.
+     *
+     * @throws IndexOutOfBoundsException When the key is not present in this object.
+     * @see #hasTimers hasTimers(int) To check if a value for the given key is present.
+     */
+    public Map<String,TimerStat> getTimers(int key) {
+        final int index = getIndex(mTimersKeys, key);
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Bad timers key dataType=" + mDataType
+                    + " key=" + key);
+        }
+        return mTimersValues[index];
+    }
+
+    /**
+     * Get the number of timer map values in this object. Can be used to iterate through
+     * the available timer maps.
+     *
+     * @see #getTimersKeyAt
+     */
+    public int getTimersKeyCount() {
+        return mTimersKeys.length;
+    }
+
+    /**
+     * Get the key for the timer map at the given index.  Index must be between 0 and the result
+     * of {@link #getTimersKeyCount getTimersKeyCount()}.
+     *
+     * @see #getTimersKeyCount
+     */
+    public int getTimersKeyAt(int index) {
+        return mTimersKeys[index];
+    }
+
+    /**
+     * Return whether this object contains a measurements map for the supplied key.
+     */
+    public boolean hasMeasurements(int key) {
+        return getIndex(mMeasurementsKeys, key) >= 0;
+    }
+
+    /**
+     * Get the measurements map for the given key.
+     *
+     * @throws IndexOutOfBoundsException When the key is not present in this object.
+     * @see #hasMeasurements To check if a value for the given key is present.
+     */
+    public Map<String,Long> getMeasurements(int key) {
+        final int index = getIndex(mMeasurementsKeys, key);
+        if (index < 0) {
+            throw new IndexOutOfBoundsException("Bad measurements key dataType=" + mDataType
+                    + " key=" + key);
+        }
+        return mMeasurementsValues[index];
+    }
+
+    /**
+     * Get the number of measurement map values in this object. Can be used to iterate through
+     * the available measurement maps.
+     *
+     * @see #getMeasurementsKeyAt
+     */
+    public int getMeasurementsKeyCount() {
+        return mMeasurementsKeys.length;
+    }
+
+    /**
+     * Get the key for the measurement map at the given index.
+     * Index must be between 0 and the result
+     * of {@link #getMeasurementsKeyCount getMeasurementsKeyCount()}.
+     *
+     * @see #getMeasurementsKeyCount
+     */
+    public int getMeasurementsKeyAt(int index) {
+        return mMeasurementsKeys[index];
+    }
+
+    /**
+     * Get the index in keys of key.
+     */
+    private static int getIndex(int[] keys, int key) {
+        return Arrays.binarySearch(keys, key);
+    }
+
+    /**
+     * Create an ArrayMap<String,HealthStats> from the given Parcel.
+     */
+    private static ArrayMap<String,HealthStats> createHealthStatsMap(Parcel in) {
+        final int count = in.readInt();
+        final ArrayMap<String,HealthStats> result = new ArrayMap<String,HealthStats>(count);
+        for (int i=0; i<count; i++) {
+            result.put(in.readString(), new HealthStats(in));
+        }
+        return result;
+    }
+
+    /**
+     * Create an ArrayMap<String,T extends Parcelable> from the given Parcel using
+     * the given Parcelable.Creator.
+     */
+    private static <T extends Parcelable> ArrayMap<String,T> createParcelableMap(Parcel in,
+            Parcelable.Creator<T> creator) {
+        final int count = in.readInt();
+        final ArrayMap<String,T> result = new ArrayMap<String,T>(count);
+        for (int i=0; i<count; i++) {
+            result.put(in.readString(), creator.createFromParcel(in));
+        }
+        return result;
+    }
+
+    /**
+     * Create an ArrayMap<String,Long> from the given Parcel.
+     */
+    private static ArrayMap<String,Long> createLongsMap(Parcel in) {
+        final int count = in.readInt();
+        final ArrayMap<String,Long> result = new ArrayMap<String,Long>(count);
+        for (int i=0; i<count; i++) {
+            result.put(in.readString(), in.readLong());
+        }
+        return result;
+    }
+}
+
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java b/core/java/android/os/health/HealthStatsParceler.aidl
similarity index 72%
copy from packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
copy to core/java/android/os/health/HealthStatsParceler.aidl
index 55f55b0..68c348b 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
+++ b/core/java/android/os/health/HealthStatsParceler.aidl
@@ -14,12 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.mtp.exceptions;
+package android.os.health;
 
-import java.io.IOException;
-
-/**
- * Exception thrown when the device is busy and the requested operation cannon be completed.
- */
-public class BusyDeviceException extends IOException {
-}
+parcelable HealthStatsParceler;
diff --git a/core/java/android/os/health/HealthStatsParceler.java b/core/java/android/os/health/HealthStatsParceler.java
new file mode 100644
index 0000000..28b3694
--- /dev/null
+++ b/core/java/android/os/health/HealthStatsParceler.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 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.health;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * Class to allow sending the HealthStats through aidl generated glue.
+ *
+ * The alternative would be to send a HealthStats object, which would
+ * require constructing one, and then immediately flattening it. This
+ * saves that step at the cost of doing the extra flattening when
+ * accessed in the same process as the writer.
+ *
+ * The HealthStatsWriter passed in the constructor is retained, so don't
+ * reuse them.
+ * @hide
+ */
+public class HealthStatsParceler implements Parcelable {
+    private HealthStatsWriter mWriter;
+    private HealthStats mHealthStats;
+
+    public static final Parcelable.Creator<HealthStatsParceler> CREATOR
+            = new Parcelable.Creator<HealthStatsParceler>() {
+        public HealthStatsParceler createFromParcel(Parcel in) {
+            return new HealthStatsParceler(in);
+        }
+
+        public HealthStatsParceler[] newArray(int size) {
+            return new HealthStatsParceler[size];
+        }
+    };
+
+    public HealthStatsParceler(HealthStatsWriter writer) {
+        mWriter = writer;
+    }
+
+    public HealthStatsParceler(Parcel in) {
+        mHealthStats = new HealthStats(in);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        // See comment on mWriter declaration above.
+        if (mWriter != null) {
+            mWriter.flattenToParcel(out);
+        } else {
+            throw new RuntimeException("Can not re-parcel HealthStatsParceler that was"
+                    + " constructed from a Parcel");
+        }
+    }
+
+    public HealthStats getHealthStats() {
+        if (mWriter != null) {
+            final Parcel parcel = Parcel.obtain();
+            mWriter.flattenToParcel(parcel);
+            parcel.setDataPosition(0);
+            mHealthStats = new HealthStats(parcel);
+            parcel.recycle();
+        }
+
+        return mHealthStats;
+    }
+}
+
diff --git a/core/java/android/os/health/HealthStatsWriter.java b/core/java/android/os/health/HealthStatsWriter.java
new file mode 100644
index 0000000..351836b
--- /dev/null
+++ b/core/java/android/os/health/HealthStatsWriter.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2016 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.health;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import java.util.Map;
+
+/**
+ * Class to write the health stats data into a parcel, so it can then be
+ * retrieved via a {@link HealthStats} object.
+ *
+ * There is an attempt to keep this class as low overhead as possible, for
+ * example storing an int[] and a long[] instead of a TimerStat[].
+ *
+ * @hide
+ */
+public class HealthStatsWriter {
+    private final HealthKeys.Constants mConstants;
+
+    // TimerStat fields
+    private final boolean[] mTimerFields;
+    private final int[] mTimerCounts;
+    private final long[] mTimerTimes;
+
+    // Measurement fields
+    private final boolean[] mMeasurementFields;
+    private final long[] mMeasurementValues;
+
+    // Stats fields
+    private final ArrayMap<String,HealthStatsWriter>[] mStatsValues;
+
+    // Timers fields
+    private final ArrayMap<String,TimerStat>[] mTimersValues;
+
+    // Measurements fields
+    private final ArrayMap<String,Long>[] mMeasurementsValues;
+
+    /**
+     * Construct a HealthStatsWriter object with the given constants.
+     *
+     * The "getDataType()" of the resulting HealthStats object will be the
+     * short name of the java class that the Constants object was initalized
+     * with.
+     */
+    public HealthStatsWriter(HealthKeys.Constants constants) {
+        mConstants = constants;
+
+        // TimerStat
+        final int timerCount = constants.getSize(HealthKeys.TYPE_TIMER);
+        mTimerFields = new boolean[timerCount];
+        mTimerCounts = new int[timerCount];
+        mTimerTimes = new long[timerCount];
+
+        // Measurement
+        final int measurementCount = constants.getSize(HealthKeys.TYPE_MEASUREMENT);
+        mMeasurementFields = new boolean[measurementCount];
+        mMeasurementValues = new long[measurementCount];
+
+        // Stats
+        final int statsCount = constants.getSize(HealthKeys.TYPE_STATS);
+        mStatsValues = new ArrayMap[statsCount];
+
+        // Timers
+        final int timersCount = constants.getSize(HealthKeys.TYPE_TIMERS);
+        mTimersValues = new ArrayMap[timersCount];
+
+        // Measurements
+        final int measurementsCount = constants.getSize(HealthKeys.TYPE_MEASUREMENTS);
+        mMeasurementsValues = new ArrayMap[measurementsCount];
+    }
+
+    /**
+     * Add a timer for the given key.
+     */
+    public void addTimer(int timerId, int count, long time) {
+        final int index = mConstants.getIndex(HealthKeys.TYPE_TIMER, timerId);
+
+        mTimerFields[index] = true;
+        mTimerCounts[index] = count;
+        mTimerTimes[index] = time;
+    }
+
+    /**
+     * Add a measurement for the given key.
+     */
+    public void addMeasurement(int measurementId, long value) {
+        final int index = mConstants.getIndex(HealthKeys.TYPE_MEASUREMENT, measurementId);
+
+        mMeasurementFields[index] = true;
+        mMeasurementValues[index] = value;
+    }
+
+    /**
+     * Add a recursive HealthStats object for the given key and string name. The value
+     * is stored as a HealthStatsWriter until this object is written to a parcel, so
+     * don't attempt to reuse the HealthStatsWriter.
+     *
+     * The value field should not be null.
+     */
+    public void addStats(int key, String name, HealthStatsWriter value) {
+        final int index = mConstants.getIndex(HealthKeys.TYPE_STATS, key);
+
+        ArrayMap<String,HealthStatsWriter> map = mStatsValues[index];
+        if (map == null) {
+            map = mStatsValues[index] = new ArrayMap<String,HealthStatsWriter>(1);
+        }
+        map.put(name, value);
+    }
+
+    /**
+     * Add a TimerStat for the given key and string name.
+     *
+     * The value field should not be null.
+     */
+    public void addTimers(int key, String name, TimerStat value) {
+        final int index = mConstants.getIndex(HealthKeys.TYPE_TIMERS, key);
+
+        ArrayMap<String,TimerStat> map = mTimersValues[index];
+        if (map == null) {
+            map = mTimersValues[index] = new ArrayMap<String,TimerStat>(1);
+        }
+        map.put(name, value);
+    }
+
+    /**
+     * Add a measurement for the given key and string name.
+     */
+    public void addMeasurements(int key, String name, long value) {
+        final int index = mConstants.getIndex(HealthKeys.TYPE_MEASUREMENTS, key);
+
+        ArrayMap<String,Long> map = mMeasurementsValues[index];
+        if (map == null) {
+            map = mMeasurementsValues[index] = new ArrayMap<String,Long>(1);
+        }
+        map.put(name, value);
+    }
+
+    /**
+     * Flattens the data in this HealthStatsWriter to the Parcel format
+     * that can be unparceled into a HealthStat.
+     * @more
+     * (Called flattenToParcel because this HealthStatsWriter itself is
+     * not parcelable and we don't flatten all the business about the
+     * HealthKeys.Constants, only the values that were actually supplied)
+     */
+    public void flattenToParcel(Parcel out) {
+        int[] keys;
+
+        // Header fields
+        out.writeString(mConstants.getDataType());
+
+        // TimerStat fields
+        out.writeInt(countBooleanArray(mTimerFields));
+        keys = mConstants.getKeys(HealthKeys.TYPE_TIMER);
+        for (int i=0; i<keys.length; i++) {
+            if (mTimerFields[i]) {
+                out.writeInt(keys[i]);
+                out.writeInt(mTimerCounts[i]);
+                out.writeLong(mTimerTimes[i]);
+            }
+        }
+
+        // Measurement fields
+        out.writeInt(countBooleanArray(mMeasurementFields));
+        keys = mConstants.getKeys(HealthKeys.TYPE_MEASUREMENT);
+        for (int i=0; i<keys.length; i++) {
+            if (mMeasurementFields[i]) {
+                out.writeInt(keys[i]);
+                out.writeLong(mMeasurementValues[i]);
+            }
+        }
+
+        // Stats
+        out.writeInt(countObjectArray(mStatsValues));
+        keys = mConstants.getKeys(HealthKeys.TYPE_STATS);
+        for (int i=0; i<keys.length; i++) {
+            if (mStatsValues[i] != null) {
+                out.writeInt(keys[i]);
+                writeHealthStatsWriterMap(out, mStatsValues[i]);
+            }
+        }
+
+        // Timers
+        out.writeInt(countObjectArray(mTimersValues));
+        keys = mConstants.getKeys(HealthKeys.TYPE_TIMERS);
+        for (int i=0; i<keys.length; i++) {
+            if (mTimersValues[i] != null) {
+                out.writeInt(keys[i]);
+                writeParcelableMap(out, mTimersValues[i]);
+            }
+        }
+
+        // Measurements
+        out.writeInt(countObjectArray(mMeasurementsValues));
+        keys = mConstants.getKeys(HealthKeys.TYPE_MEASUREMENTS);
+        for (int i=0; i<keys.length; i++) {
+            if (mMeasurementsValues[i] != null) {
+                out.writeInt(keys[i]);
+                writeLongsMap(out, mMeasurementsValues[i]);
+            }
+        }
+    }
+
+    /**
+     * Count how many of the fields have been set.
+     */
+    private static int countBooleanArray(boolean[] fields) {
+        int count = 0;
+        final int N = fields.length;
+        for (int i=0; i<N; i++) {
+            if (fields[i]) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Count how many of the fields have been set.
+     */
+    private static <T extends Object> int countObjectArray(T[] fields) {
+        int count = 0;
+        final int N = fields.length;
+        for (int i=0; i<N; i++) {
+            if (fields[i] != null) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Write a map of String to HealthStatsWriter to the Parcel.
+     */
+    private static void writeHealthStatsWriterMap(Parcel out,
+            ArrayMap<String,HealthStatsWriter> map) {
+        final int N = map.size();
+        out.writeInt(N);
+        for (int i=0; i<N; i++) {
+            out.writeString(map.keyAt(i));
+            map.valueAt(i).flattenToParcel(out);
+        }
+    }
+
+    /**
+     * Write a map of String to Parcelables to the Parcel.
+     */
+    private static <T extends Parcelable> void writeParcelableMap(Parcel out,
+            ArrayMap<String,T> map) {
+        final int N = map.size();
+        out.writeInt(N);
+        for (int i=0; i<N; i++) {
+            out.writeString(map.keyAt(i));
+            map.valueAt(i).writeToParcel(out, 0);
+        }
+    }
+
+    /**
+     * Write a map of String to Longs to the Parcel.
+     */
+    private static void writeLongsMap(Parcel out, ArrayMap<String,Long> map) {
+        final int N = map.size();
+        out.writeInt(N);
+        for (int i=0; i<N; i++) {
+            out.writeString(map.keyAt(i));
+            out.writeLong(map.valueAt(i));
+        }
+    }
+}
+
+
diff --git a/core/java/android/os/health/PackageHealthStats.java b/core/java/android/os/health/PackageHealthStats.java
new file mode 100644
index 0000000..2c30d5f
--- /dev/null
+++ b/core/java/android/os/health/PackageHealthStats.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 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.health;
+
+/**
+ * Keys for {@link HealthStats} returned from
+ * {@link HealthStats#getStats(int) HealthStats.getStats(int)} with the
+ * {@link UidHealthStats#STATS_PACKAGES UidHealthStats.STATS_PACKAGES} key.
+ */
+public final class PackageHealthStats {
+
+    private PackageHealthStats() {
+    }
+
+    /**
+     * Key for a HealthStats with {@link ServiceHealthStats} keys for each of the
+     * services defined in this apk.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_STATS)
+    public static final int STATS_SERVICES = HealthKeys.BASE_PACKAGE + 1;
+
+    /**
+     * Key for a map of the number of times that a package's wakeup alarms have fired
+     * while the device was on battery.
+     *
+     * @see android.app.AlarmManager.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENTS)
+    public static final int MEASUREMENTS_WAKEUP_ALARMS_COUNT = HealthKeys.BASE_PACKAGE + 2;
+
+    /**
+     * @hide
+     */
+    public static final HealthKeys.Constants CONSTANTS
+            = new HealthKeys.Constants(PackageHealthStats.class);
+}
diff --git a/core/java/android/os/health/PidHealthStats.java b/core/java/android/os/health/PidHealthStats.java
new file mode 100644
index 0000000..fe3c02c
--- /dev/null
+++ b/core/java/android/os/health/PidHealthStats.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 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.health;
+
+/**
+ * Keys for {@link HealthStats} returned from
+ * {@link HealthStats#getStats(int) HealthStats.getStats(int)} with the
+ * {@link UidHealthStats#STATS_PIDS UidHealthStats.STATS_PIDS} key.
+ */
+public final class PidHealthStats {
+
+    private PidHealthStats() {
+    }
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WAKE_NESTING_COUNT = HealthKeys.BASE_PID + 1;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WAKE_SUM_MS = HealthKeys.BASE_PID + 2;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WAKE_START_MS = HealthKeys.BASE_PID + 3;
+
+    /**
+     * @hide
+     */
+    public static final HealthKeys.Constants CONSTANTS = new HealthKeys.Constants(PidHealthStats.class);
+}
diff --git a/core/java/android/os/health/ProcessHealthStats.java b/core/java/android/os/health/ProcessHealthStats.java
new file mode 100644
index 0000000..e004ecb
--- /dev/null
+++ b/core/java/android/os/health/ProcessHealthStats.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 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.health;
+
+/**
+ * Keys for {@link HealthStats} returned from
+ * {@link HealthStats#getStats(int) HealthStats.getStats(int)} with the
+ * {@link UidHealthStats#STATS_PROCESSES UidHealthStats.STATS_PROCESSES} key.
+ */
+public final class ProcessHealthStats {
+
+    private ProcessHealthStats() {
+    }
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_USER_TIME_MS = HealthKeys.BASE_PROCESS + 1;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_SYSTEM_TIME_MS = HealthKeys.BASE_PROCESS + 2;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_STARTS_COUNT = HealthKeys.BASE_PROCESS + 3;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_CRASHES_COUNT = HealthKeys.BASE_PROCESS + 4;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_ANR_COUNT = HealthKeys.BASE_PROCESS + 5;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_FOREGROUND_MS = HealthKeys.BASE_PROCESS + 6;
+
+    /**
+     * @hide
+     */
+    public static final HealthKeys.Constants CONSTANTS = new HealthKeys.Constants(ProcessHealthStats.class);
+}
diff --git a/core/java/android/os/health/ServiceHealthStats.java b/core/java/android/os/health/ServiceHealthStats.java
new file mode 100644
index 0000000..802ad31
--- /dev/null
+++ b/core/java/android/os/health/ServiceHealthStats.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 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.health;
+
+/**
+ * Keys for {@link HealthStats} returned from
+ * {@link HealthStats#getStats(int) HealthStats.getStats(int)} with the
+ * {@link PackageHealthStats#STATS_SERVICES PackageHealthStats.STATS_SERVICES} key.
+ */
+public final class ServiceHealthStats {
+
+    private ServiceHealthStats() {
+    }
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_START_SERVICE_COUNT = HealthKeys.BASE_SERVICE + 1;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_LAUNCH_COUNT = HealthKeys.BASE_SERVICE + 2;
+
+    /**
+     * @hide
+     */
+    public static final HealthKeys.Constants CONSTANTS
+            = new HealthKeys.Constants(ServiceHealthStats.class);
+}
diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java
new file mode 100644
index 0000000..520e84e
--- /dev/null
+++ b/core/java/android/os/health/SystemHealthManager.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2016 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.health;
+
+import android.content.Context;
+import android.os.BatteryStats;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.app.IBatteryStats;
+
+/**
+ * Provides access to data about how various system resources are used by applications.
+ * @more
+ * <b>Battery Usage</b><br>
+ * The statistics related to power (battery) usage are recorded since the device
+ * was last unplugged. It is expected that applications schedule more work to do
+ * while the device is plugged in (e.g. using {@link android.app.job.JobScheduler
+ * JobScheduler}), and while that can affect charging rates, it is still preferable
+ * to actually draining the battery.
+ */
+public class SystemHealthManager {
+    private final IBatteryStats mBatteryStats;
+
+    /**
+     * Construct a new SystemHealthManager object.
+     * @hide
+     */
+    public SystemHealthManager() {
+        mBatteryStats = IBatteryStats.Stub.asInterface(
+            ServiceManager.getService(BatteryStats.SERVICE_NAME));
+    }
+
+    /**
+     * Obtain a SystemHealthManager object for the supplied context.
+     */
+    public static SystemHealthManager from(Context context) {
+        return (SystemHealthManager)context.getSystemService(Context.SYSTEM_HEALTH_SERVICE);
+    }
+
+    /**
+     * Return a {@link HealthStats} object containing a snapshot of system health
+     * metrics for the given uid (user-id, which in usually corresponds to application).
+     * @more
+     *
+     * An application must hold the {@link android.Manifest.permission#BATTERY_STATS
+     * android.permission.BATTERY_STATS} permission in order to retrieve any HealthStats
+     * other than its own.
+     *
+     * @param uid User ID for a given application.
+     * @return A {@link HealthStats} object containing the metrics for the requested
+     * application. The keys for this HealthStats object will be from the {@link UidHealthStats}
+     * class.
+     * @see Process#myUid()
+     */
+    public HealthStats takeUidSnapshot(int uid) {
+        try {
+            final HealthStatsParceler parceler = mBatteryStats.takeUidSnapshot(uid);
+            return parceler.getHealthStats();
+        } catch (RemoteException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    /**
+     * Return a {@link HealthStats} object containing a snapshot of system health
+     * metrics for the application calling this API. This method is the same as calling
+     * {@code takeUidSnapshot(Process.myUid())}.
+     *
+     * @return A {@link HealthStats} object containing the metrics for this application. The keys
+     * for this HealthStats object will be from the {@link UidHealthStats} class.
+     */
+    public HealthStats takeMyUidSnapshot() {
+        return takeUidSnapshot(Process.myUid());
+    }
+
+    /**
+     * Return a {@link HealthStats} object containing a snapshot of system health
+     * metrics for the given uids (user-id, which in usually corresponds to application).
+     * @more
+     *
+     * An application must hold the {@link android.Manifest.permission#BATTERY_STATS
+     * android.permission.BATTERY_STATS} permission in order to retrieve any HealthStats
+     * other than its own.
+     *
+     * @param uids An array of User IDs to retrieve.
+     * @return An array of {@link HealthStats} objects containing the metrics for each of
+     * the requested uids. The keys for this HealthStats object will be from the
+     * {@link UidHealthStats} class.
+     */
+    public HealthStats[] takeUidSnapshots(int[] uids) {
+        try {
+            final HealthStatsParceler[] parcelers = mBatteryStats.takeUidSnapshots(uids);
+            final HealthStats[] results = new HealthStats[uids.length];
+            final int N = uids.length;
+            for (int i=0; i<N; i++) {
+                results[i] = parcelers[i].getHealthStats();
+            }
+            return results;
+        } catch (RemoteException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+}
+
diff --git a/core/java/android/os/health/TimerStat.java b/core/java/android/os/health/TimerStat.java
new file mode 100644
index 0000000..fc51b60
--- /dev/null
+++ b/core/java/android/os/health/TimerStat.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2016 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.health;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A TimerStat object stores a count and a time.
+ *
+ * @more
+ * When possible, the other APIs in this package avoid requiring a TimerStat
+ * object to be constructed, even internally, but the getTimers method on
+ * {@link android.os.health.HealthStats} does require TimerStat objects.
+ */
+public class TimerStat implements Parcelable {
+    private int mCount;
+    private long mTime;
+
+    /**
+     * The CREATOR instance for use by aidl Binder interfaces.
+     */
+    public static final Parcelable.Creator<TimerStat> CREATOR
+            = new Parcelable.Creator<TimerStat>() {
+        public TimerStat createFromParcel(Parcel in) {
+            return new TimerStat(in);
+        }
+
+        public TimerStat[] newArray(int size) {
+            return new TimerStat[size];
+        }
+    };
+
+    /**
+     * Construct an empty TimerStat object with the count and time set to 0.
+     */
+    public TimerStat() {
+    }
+
+    /**
+     * Construct a TimerStat object with the supplied count and time fields.
+     *
+     * @param count The count
+     * @param time The time
+     */
+    public TimerStat(int count, long time) {
+        mCount = count;
+        mTime = time;
+    }
+
+    /**
+     * Construct a TimerStat object reading the values from a {@link android.os.Parcel Parcel}
+     * object.
+     */
+    public TimerStat(Parcel in) {
+        mCount = in.readInt();
+        mTime = in.readLong();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Write this TimerStat object to a parcel.
+     */
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mCount);
+        out.writeLong(mTime);
+    }
+
+    /**
+     * Set the count for this timer.
+     */
+    public void setCount(int count) {
+        mCount = count;
+    }
+
+    /**
+     * Get the count for this timer.
+     */
+    public int getCount() {
+        return mCount;
+    }
+
+    /**
+     * Set the time for this timer.
+     */
+    public void setTime(long time) {
+        mTime = time;
+    }
+
+    /**
+     * Get the time for this timer.
+     */
+    public long getTime() {
+        return mTime;
+    }
+}
diff --git a/core/java/android/os/health/UidHealthStats.java b/core/java/android/os/health/UidHealthStats.java
new file mode 100644
index 0000000..c7d257f
--- /dev/null
+++ b/core/java/android/os/health/UidHealthStats.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2016 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.health;
+
+/**
+ * Keys for {@link HealthStats} returned from
+ * {@link SystemHealthManager#takeUidSnapshot(int) SystemHealthManager.takeUidSnapshot(int)},
+ * {@link SystemHealthManager#takeMyUidSnapshot() SystemHealthManager.takeMyUidSnapshot()}, and
+ * {@link SystemHealthManager#takeUidSnapshots(int[]) SystemHealthManager.takeUidSnapshots(int[])}.
+ */
+public final class UidHealthStats {
+
+    private UidHealthStats() {
+    }
+
+    /**
+     * How many milliseconds this statistics report covers in wall-clock time while the
+     * device was on battery including both screen-on and screen-off time.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_REALTIME_BATTERY_MS = HealthKeys.BASE_UID + 1;
+
+    /**
+     * How many milliseconds this statistics report covers that the CPU was running while the
+     * device was on battery including both screen-on and screen-off time.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_UPTIME_BATTERY_MS = HealthKeys.BASE_UID + 2;
+
+    /**
+     * How many milliseconds this statistics report covers in wall-clock time while the
+     * device was on battery including both screen-on and screen-off time.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS = HealthKeys.BASE_UID + 3;
+
+    /**
+     * How many milliseconds this statistics report covers that the CPU was running while the
+     * device was on battery including both screen-on and screen-off time.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS = HealthKeys.BASE_UID + 4;
+
+    /**
+     * Key for a TimerStat for the times a
+     * {@link android.os.PowerManager#FULL_WAKE_LOCK full wake lock}
+     * was acquired for this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
+    public static final int TIMERS_WAKELOCKS_FULL = HealthKeys.BASE_UID + 5;
+
+    /**
+     * Key for a TimerStat for the times a
+     * {@link android.os.PowerManager#PARTIAL_WAKE_LOCK full wake lock}
+     * was acquired for this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
+    public static final int TIMERS_WAKELOCKS_PARTIAL = HealthKeys.BASE_UID + 6;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
+    public static final int TIMERS_WAKELOCKS_WINDOW = HealthKeys.BASE_UID + 7;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
+    public static final int TIMERS_WAKELOCKS_DRAW = HealthKeys.BASE_UID + 8;
+
+    /**
+     * Key for a map of Timers for the sync adapter syncs that were done for
+     * this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
+    public static final int TIMERS_SYNCS = HealthKeys.BASE_UID + 9;
+
+    /**
+     * Key for a map of Timers for the {@link android.app.job.JobScheduler} jobs for
+     * this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
+    public static final int TIMERS_JOBS = HealthKeys.BASE_UID + 10;
+
+    /**
+     * Key for a timer for the applications use of the GPS sensor.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_GPS_SENSOR = HealthKeys.BASE_UID + 11;
+
+    /**
+     * Key for a map of the sensor usage for this uid. The keys are a
+     * string representation of the handle for the sensor.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMERS)
+    public static final int TIMERS_SENSORS = HealthKeys.BASE_UID + 12;
+
+    /**
+     * Key for a HealthStats with {@link PidHealthStats} keys for each of the
+     * currently running processes for this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_STATS)
+    public static final int STATS_PIDS = HealthKeys.BASE_UID + 13;
+
+    /**
+     * Key for a HealthStats with {@link ProcessHealthStats} keys for each of the
+     * named processes for this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_STATS)
+    public static final int STATS_PROCESSES = HealthKeys.BASE_UID + 14;
+
+    /**
+     * Key for a HealthStats with {@link PackageHealthStats} keys for each of the
+     * APKs that share this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_STATS)
+    public static final int STATS_PACKAGES = HealthKeys.BASE_UID + 15;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_IDLE_MS = HealthKeys.BASE_UID + 16;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_RX_MS = HealthKeys.BASE_UID + 17;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_TX_MS = HealthKeys.BASE_UID + 18;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_POWER_MAMS = HealthKeys.BASE_UID + 19;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_IDLE_MS = HealthKeys.BASE_UID + 20;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_RX_MS = HealthKeys.BASE_UID + 21;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_TX_MS = HealthKeys.BASE_UID + 22;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_POWER_MAMS = HealthKeys.BASE_UID + 23;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_IDLE_MS = HealthKeys.BASE_UID + 24;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_RX_MS = HealthKeys.BASE_UID + 25;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_TX_MS = HealthKeys.BASE_UID + 26;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_POWER_MAMS = HealthKeys.BASE_UID + 27;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_RUNNING_MS = HealthKeys.BASE_UID + 28;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_FULL_LOCK_MS = HealthKeys.BASE_UID + 29;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_WIFI_SCAN = HealthKeys.BASE_UID + 30;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_MULTICAST_MS = HealthKeys.BASE_UID + 31;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_AUDIO = HealthKeys.BASE_UID + 32;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_VIDEO = HealthKeys.BASE_UID + 33;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_FLASHLIGHT = HealthKeys.BASE_UID + 34;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_CAMERA = HealthKeys.BASE_UID + 35;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_FOREGROUND_ACTIVITY = HealthKeys.BASE_UID + 36;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_BLUETOOTH_SCAN = HealthKeys.BASE_UID + 37;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_PROCESS_STATE_TOP_MS = HealthKeys.BASE_UID + 38;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS = HealthKeys.BASE_UID + 39;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_PROCESS_STATE_TOP_SLEEPING_MS = HealthKeys.BASE_UID + 40;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_PROCESS_STATE_FOREGROUND_MS = HealthKeys.BASE_UID + 41;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_PROCESS_STATE_BACKGROUND_MS = HealthKeys.BASE_UID + 42;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_PROCESS_STATE_CACHED_MS = HealthKeys.BASE_UID + 43;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_VIBRATOR = HealthKeys.BASE_UID + 44;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_OTHER_USER_ACTIVITY_COUNT = HealthKeys.BASE_UID + 45;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = HealthKeys.BASE_UID + 46;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT = HealthKeys.BASE_UID + 47;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_RX_BYTES = HealthKeys.BASE_UID + 48;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_TX_BYTES = HealthKeys.BASE_UID + 49;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_RX_BYTES = HealthKeys.BASE_UID + 50;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_TX_BYTES = HealthKeys.BASE_UID + 51;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_RX_BYTES = HealthKeys.BASE_UID + 52;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_TX_BYTES = HealthKeys.BASE_UID + 53;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_RX_PACKETS = HealthKeys.BASE_UID + 54;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_MOBILE_TX_PACKETS = HealthKeys.BASE_UID + 55;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_RX_PACKETS = HealthKeys.BASE_UID + 56;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_WIFI_TX_PACKETS = HealthKeys.BASE_UID + 57;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_RX_PACKETS = HealthKeys.BASE_UID + 58;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = HealthKeys.BASE_UID + 59;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_TIMER)
+    public static final int TIMER_MOBILE_RADIO_ACTIVE = HealthKeys.BASE_UID + 61;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_USER_CPU_TIME_US = HealthKeys.BASE_UID + 62;
+
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_SYSTEM_CPU_TIME_US = HealthKeys.BASE_UID + 63;
+
+    /**
+     * An estimate of the number of milliamp-microsends used by this uid.
+     */
+    @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
+    public static final int MEASUREMENT_CPU_POWER_MAUS = HealthKeys.BASE_UID + 64;
+
+    /**
+     * @hide
+     */
+    public static final HealthKeys.Constants CONSTANTS = new HealthKeys.Constants(UidHealthStats.class);
+}
+
diff --git a/core/java/android/os/health/package.html b/core/java/android/os/health/package.html
new file mode 100644
index 0000000..3a46a5b
--- /dev/null
+++ b/core/java/android/os/health/package.html
@@ -0,0 +1,39 @@
+<html>
+<body>
+
+The android.os.health package contains a set of classes to provide data
+to track the system resources of applications.
+<p>
+Applications running in the background are responsible for a significant amount 
+of battery usage on a typical android device. There are several things that 
+applications can do in order to reduce their impact. For example, by using 
+{@link android.app.job.JobScheduler JobScheduler}, an application does not need 
+to independently monitor whether the network is available, whether the device is 
+plugged in, etc.  In addition to being simpler to use, the application's 
+services are only started when the required conditions have been met.  But even 
+when using the appropriate helper APIs, applications still can reduce their 
+footprint. This package provides more insight into what is going on behind the 
+scenes when an application is running.
+<p>
+Application data is tracked by which user id (uid) is using particular 
+resources. A snapshot of an application's measurements can be taken with the
+{@link android.os.health.SystemHealthManager#takeMyUidSnapshot() SystemHealth.takeMyUidSnapshot()} 
+method. The {@link android.os.health.HealthStats} object returned contains the 
+statistics.
+<p>
+<b>HealthStats</b><br>
+In order to be returned efficiently, the {@link android.os.health.HealthStats} 
+class uses a set of int keys to identify the data returned. The
+{@link android.os.health.UidHealthStats}, {@link android.os.health.PidHealthStats},
+{@link android.os.health.PackageHealthStats} , {@link android.os.health.ProcessHealthStats},
+and {@link android.os.health.ServiceHealthStats} classes provide those constants.
+Each {@link android.os.health.HealthStats} object will be associated with
+exactly one of those classes. The object returned from
+{@link android.os.health.SystemHealthManager#takeMyUidSnapshot() SystemHealth.takeMyUidSnapshot()}
+will be using the {@link android.os.health.UidHealthStats} keys, as it contains all
+of the data available for that uid.
+
+
+</body>
+</html>
+
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index e7c4a07..e2ae133 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -179,6 +179,7 @@
          * <li>{@link #VOICEMAIL_TYPE}</li>
          * <li>{@link #REJECTED_TYPE}</li>
          * <li>{@link #BLOCKED_TYPE}</li>
+         * <li>{@link #ANSWERED_EXTERNALLY_TYPE}</li>
          * </ul>
          * </p>
          */
@@ -196,6 +197,12 @@
         public static final int REJECTED_TYPE = 5;
         /** Call log type for calls blocked automatically. */
         public static final int BLOCKED_TYPE = 6;
+        /**
+         * Call log type for a call which was answered on another device.  Used in situations where
+         * a call rings on multiple devices simultaneously and it ended up being answered on a
+         * device other than the current one.
+         */
+        public static final int ANSWERED_EXTERNALLY_TYPE = 7;
 
         /**
          * Bit-mask describing features of the call (e.g. video).
@@ -207,6 +214,9 @@
         /** Call had video. */
         public static final int FEATURES_VIDEO = 0x1;
 
+        /** Call was pulled externally. */
+        public static final int FEATURES_PULLED_EXTERNALLY = 0x2;
+
         /**
          * The phone number as the user entered it.
          * <P>Type: TEXT</P>
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 0065cd9..4ad7969 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -119,8 +119,6 @@
     public static final String EXTRA_PROMPT = "android.provider.extra.PROMPT";
 
     /** {@hide} */
-    public static final String ACTION_MANAGE_ROOT = "android.provider.action.MANAGE_ROOT";
-    /** {@hide} */
     public static final String ACTION_MANAGE_DOCUMENT = "android.provider.action.MANAGE_DOCUMENT";
 
     /** {@hide} */
@@ -381,20 +379,18 @@
          * @see DocumentsProvider#queryChildDocuments(String, String[], String)
          * @hide
          */
-
         public static final int FLAG_ARCHIVE = 1 << 15;
+
         /**
-         * Flag indicating that document titles should be hidden when viewing
-         * this directory in a larger format grid. For example, a directory
-         * containing only images may want the image thumbnails to speak for
-         * themselves. Only valid when {@link #COLUMN_MIME_TYPE} is
-         * {@link #MIME_TYPE_DIR}.
+         * Flag indicating that a document is not complete, likely its
+         * contents are being downloaded. Partial files cannot be opened,
+         * copied, moved in the UI. But they can be deleted and retried
+         * if they represent a failed download.
          *
          * @see #COLUMN_FLAGS
-         * @see #FLAG_DIR_PREFERS_GRID
          * @hide
          */
-        public static final int FLAG_DIR_HIDE_GRID_TITLES = 1 << 16;
+        public static final int FLAG_PARTIAL = 1 << 16;
     }
 
     /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d43ff4e..049d585 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -217,21 +217,6 @@
             "android.settings.ACCESSIBILITY_SETTINGS";
 
     /**
-     * Activity Action: Launch the screen reader tutorial.
-     * <p>
-     * In some cases, a matching Activity may not exist, so ensure you
-     * safeguard against this.
-     * <p>
-     * Input: Nothing.
-     * <p>
-     * Output: Nothing.
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_SCREEN_READER_TUTORIAL =
-            "android.settings.SCREEN_READER_TUTORIAL";
-
-
-    /**
      * Activity Action: Show settings to control access to usage information.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
@@ -2723,24 +2708,6 @@
         public static final String VOLUME_MASTER = "volume_master";
 
         /**
-         * Master volume mute (int 1 = mute, 0 = not muted).
-         *
-         * @hide
-         */
-        public static final String VOLUME_MASTER_MUTE = "volume_master_mute";
-
-        private static final Validator VOLUME_MASTER_MUTE_VALIDATOR = sBooleanValidator;
-
-        /**
-         * Microphone mute (int 1 = mute, 0 = not muted).
-         *
-         * @hide
-         */
-        public static final String MICROPHONE_MUTE = "microphone_mute";
-
-        private static final Validator MICROPHONE_MUTE_VALIDATOR = sBooleanValidator;
-
-        /**
          * Master mono (int 1 = mono, 0 = normal).
          *
          * @hide
@@ -3530,8 +3497,6 @@
             PRIVATE_SETTINGS.add(SCREEN_AUTO_BRIGHTNESS_ADJ);
             PRIVATE_SETTINGS.add(VIBRATE_INPUT_DEVICES);
             PRIVATE_SETTINGS.add(VOLUME_MASTER);
-            PRIVATE_SETTINGS.add(VOLUME_MASTER_MUTE);
-            PRIVATE_SETTINGS.add(MICROPHONE_MUTE);
             PRIVATE_SETTINGS.add(MASTER_MONO);
             PRIVATE_SETTINGS.add(NOTIFICATIONS_USE_RING_VOLUME);
             PRIVATE_SETTINGS.add(VIBRATE_IN_SILENT);
@@ -3609,8 +3574,6 @@
             VALIDATORS.put(ADVANCED_SETTINGS, ADVANCED_SETTINGS_VALIDATOR);
             VALIDATORS.put(SCREEN_AUTO_BRIGHTNESS_ADJ, SCREEN_AUTO_BRIGHTNESS_ADJ_VALIDATOR);
             VALIDATORS.put(VIBRATE_INPUT_DEVICES, VIBRATE_INPUT_DEVICES_VALIDATOR);
-            VALIDATORS.put(VOLUME_MASTER_MUTE, VOLUME_MASTER_MUTE_VALIDATOR);
-            VALIDATORS.put(MICROPHONE_MUTE, MICROPHONE_MUTE_VALIDATOR);
             VALIDATORS.put(MASTER_MONO, MASTER_MONO_VALIDATOR);
             VALIDATORS.put(NOTIFICATIONS_USE_RING_VOLUME, NOTIFICATIONS_USE_RING_VOLUME_VALIDATOR);
             VALIDATORS.put(VIBRATE_IN_SILENT, VIBRATE_IN_SILENT_VALIDATOR);
@@ -7786,6 +7749,31 @@
         public static final String ALARM_MANAGER_CONSTANTS = "alarm_manager_constants";
 
         /**
+         * ShortcutManager specific settings.
+         * This is encoded as a key=value list, separated by commas. Ex:
+         *
+         * "reset_interval_sec=86400,max_daily_updates=5"
+         *
+         * The following keys are supported:
+         *
+         * <pre>
+         * reset_interval_sec              (long)
+         * max_daily_updates               (int)
+         * max_icon_dimension_dp           (int, DP)
+         * max_icon_dimension_dp_lowram    (int, DP)
+         * max_shortcuts                   (int)
+         * icon_quality                    (int, 0-100)
+         * icon_format                     (String)
+         * </pre>
+         *
+         * <p>
+         * Type: string
+         * @hide
+         * @see com.android.server.pm.ShortcutService.ConfigConstants
+         */
+        public static final String SHORTCUT_MANAGER_CONSTANTS = "shortcut_manager_constants";
+
+        /**
          * Get the key that retrieves a bluetooth headset's priority.
          * @hide
          */
diff --git a/core/java/android/security/net/config/XmlConfigSource.java b/core/java/android/security/net/config/XmlConfigSource.java
index 2a8773c..d57d0f5 100644
--- a/core/java/android/security/net/config/XmlConfigSource.java
+++ b/core/java/android/security/net/config/XmlConfigSource.java
@@ -339,7 +339,7 @@
                 }
                 if (mDebugBuild) {
                     debugConfigBuilder =
-                            parseConfigEntry(parser, seenDomains, null, CONFIG_DEBUG).get(0).first;
+                            parseConfigEntry(parser, null, null, CONFIG_DEBUG).get(0).first;
                 } else {
                     XmlUtils.skipCurrentTag(parser);
                 }
@@ -348,6 +348,11 @@
                 XmlUtils.skipCurrentTag(parser);
             }
         }
+        // If debug is true and there was no debug-overrides in the file check for an extra
+        // _debug resource.
+        if (mDebugBuild && debugConfigBuilder == null) {
+            debugConfigBuilder = parseDebugOverridesResource();
+        }
 
         // Use the platform default as the parent of the base config for any values not provided
         // there. If there is no base config use the platform default.
@@ -385,6 +390,43 @@
         mDomainMap = configs;
     }
 
+    private NetworkSecurityConfig.Builder parseDebugOverridesResource()
+            throws IOException, XmlPullParserException, ParserException {
+        Resources resources = mContext.getResources();
+        String packageName = resources.getResourcePackageName(mResourceId);
+        String entryName = resources.getResourceEntryName(mResourceId);
+        int resId = resources.getIdentifier(entryName + "_debug", "xml", packageName);
+        // No debug-overrides resource was found, nothing to parse.
+        if (resId == 0) {
+            return null;
+        }
+        NetworkSecurityConfig.Builder debugConfigBuilder = null;
+        // Parse debug-overrides out of the _debug resource.
+        try (XmlResourceParser parser = resources.getXml(resId)) {
+            XmlUtils.beginDocument(parser, "network-security-config");
+            int outerDepth = parser.getDepth();
+            boolean seenDebugOverrides = false;
+            while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+                if ("debug-overrides".equals(parser.getName())) {
+                    if (seenDebugOverrides) {
+                        throw new ParserException(parser, "Only one debug-overrides allowed");
+                    }
+                    if (mDebugBuild) {
+                        debugConfigBuilder =
+                                parseConfigEntry(parser, null, null, CONFIG_DEBUG).get(0).first;
+                    } else {
+                        XmlUtils.skipCurrentTag(parser);
+                    }
+                    seenDebugOverrides = true;
+                } else {
+                    XmlUtils.skipCurrentTag(parser);
+                }
+            }
+        }
+
+        return debugConfigBuilder;
+    }
+
     public static class ParserException extends Exception {
 
         public ParserException(XmlPullParser parser, String message, Throwable cause) {
diff --git a/core/java/android/service/notification/NotificationRankerService.java b/core/java/android/service/notification/NotificationRankerService.java
index e325354..47fdac6 100644
--- a/core/java/android/service/notification/NotificationRankerService.java
+++ b/core/java/android/service/notification/NotificationRankerService.java
@@ -119,7 +119,13 @@
     @Override
     public void registerAsSystemService(Context context, ComponentName componentName,
             int currentUser)  {
-        throw new IllegalStateException("the ranker may not start itself.");
+        throw new UnsupportedOperationException("the ranker lifecycle is managed by the system.");
+    }
+
+    /** @hide */
+    @Override
+    public void unregisterAsSystemService()  {
+        throw new UnsupportedOperationException("the ranker lifecycle is managed by the system.");
     }
 
     @Override
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index bfe5c3f..a1bc2d1 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -247,23 +247,22 @@
      */
     public static Metrics isBoring(CharSequence text, TextPaint paint,
             TextDirectionHeuristic textDir, Metrics metrics) {
-        char[] temp = TextUtils.obtain(500);
-        int length = text.length();
+        final int MAX_BUF_LEN = 500;
+        final char[] buffer = TextUtils.obtain(MAX_BUF_LEN);
+        final int textLength = text.length();
         boolean boring = true;
 
         outer:
-        for (int i = 0; i < length; i += 500) {
-            int j = i + 500;
+        for (int start = 0; start < textLength; start += MAX_BUF_LEN) {
+            final int end = Math.min(start + MAX_BUF_LEN, textLength);
 
-            if (j > length)
-                j = length;
+            // No need to worry about getting half codepoints, since we reject surrogate code units
+            // as non-boring as soon we see one.
+            TextUtils.getChars(text, start, end, buffer, 0);
 
-            TextUtils.getChars(text, i, j, temp, 0);
-
-            int n = j - i;
-
-            for (int a = 0; a < n; a++) {
-                char c = temp[a];
+            final int len = end - start;
+            for (int i = 0; i < len; i++) {
+                final char c = buffer[i];
 
                 if (c == '\n' || c == '\t' ||
                         (c >= 0x0590 && c <= 0x08FF) ||  // RTL scripts
@@ -279,17 +278,19 @@
                 }
             }
 
-            if (textDir != null && textDir.isRtl(temp, 0, n)) {
+            // TODO: This looks a little suspicious, and in some cases can result in O(n^2)
+            // run time. Consider moving outside the loop.
+            if (textDir != null && textDir.isRtl(buffer, 0, len)) {
                boring = false;
                break outer;
             }
         }
 
-        TextUtils.recycle(temp);
+        TextUtils.recycle(buffer);
 
         if (boring && text instanceof Spanned) {
             Spanned sp = (Spanned) text;
-            Object[] styles = sp.getSpans(0, length, ParagraphStyle.class);
+            Object[] styles = sp.getSpans(0, textLength, ParagraphStyle.class);
             if (styles.length > 0) {
                 boring = false;
             }
@@ -302,7 +303,7 @@
             }
 
             TextLine line = TextLine.obtain();
-            line.set(paint, text, 0, length, Layout.DIR_LEFT_TO_RIGHT,
+            line.set(paint, text, 0, textLength, Layout.DIR_LEFT_TO_RIGHT,
                     Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null);
             fm.width = (int) Math.ceil(line.metrics(fm));
             TextLine.recycle(line);
diff --git a/core/java/android/text/Hyphenator.java b/core/java/android/text/Hyphenator.java
index 568b267..085613f 100644
--- a/core/java/android/text/Hyphenator.java
+++ b/core/java/android/text/Hyphenator.java
@@ -185,7 +185,6 @@
             "de-1901", "de-1996", "de-CH-1901",
             "en-US",
             "es",
-            "eu",
             "hu",
             "hy",
             "nb",
diff --git a/core/java/android/text/style/TtsSpan.java b/core/java/android/text/style/TtsSpan.java
index 93a156b..e9153dd 100644
--- a/core/java/android/text/style/TtsSpan.java
+++ b/core/java/android/text/style/TtsSpan.java
@@ -1013,7 +1013,7 @@
          * @return This instance.
          */
         public MeasureBuilder setIntegerPart(long integerPart) {
-            return setNumber(String.valueOf(integerPart));
+            return setIntegerPart(String.valueOf(integerPart));
         }
 
         /**
diff --git a/core/java/android/transition/ArcMotion.java b/core/java/android/transition/ArcMotion.java
index fa4c8d2..70443ba 100644
--- a/core/java/android/transition/ArcMotion.java
+++ b/core/java/android/transition/ArcMotion.java
@@ -15,13 +15,13 @@
  */
 package android.transition;
 
-import com.android.internal.R;
-
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Path;
 import android.util.AttributeSet;
 
+import com.android.internal.R;
+
 /**
  * A PathMotion that generates a curved path along an arc on an imaginary circle containing
  * the two points. If the horizontal distance between the points is less than the vertical
@@ -207,7 +207,7 @@
             ey = (startY + endY) / 2;
         } else {
             float deltaX = endX - startX;
-            float deltaY = startY - endY; // Y is inverted compared to diagram above.
+            float deltaY = endY - startY;
             // hypotenuse squared.
             float h2 = deltaX * deltaX + deltaY * deltaY;
 
@@ -219,24 +219,35 @@
             float midDist2 = h2 * 0.25f;
 
             float minimumArcDist2 = 0;
+            boolean isQuadrant1Or3 = (deltaX * deltaY) > 0;
 
-            if (Math.abs(deltaX) < Math.abs(deltaY)) {
+            if ((Math.abs(deltaX) < Math.abs(deltaY))) {
                 // Similar triangles bfa and bde mean that (ab/fb = eb/bd)
                 // Therefore, eb = ab * bd / fb
                 // ab = hypotenuse
                 // bd = hypotenuse/2
                 // fb = deltaY
                 float eDistY = h2 / (2 * deltaY);
-                ey = endY + eDistY;
-                ex = endX;
+                if (isQuadrant1Or3) {
+                    ey = startY + eDistY;
+                    ex = startX;
+                } else {
+                    ey = endY - eDistY;
+                    ex = endX;
+                }
 
                 minimumArcDist2 = midDist2 * mMinimumVerticalTangent
                         * mMinimumVerticalTangent;
             } else {
                 // Same as above, but flip X & Y
                 float eDistX = h2 / (2 * deltaX);
-                ex = endX + eDistX;
-                ey = endY;
+                if (isQuadrant1Or3) {
+                    ex = endX - eDistX;
+                    ey = endY;
+                } else {
+                    ex = startX + eDistX;
+                    ey = startY;
+                }
 
                 minimumArcDist2 = midDist2 * mMinimumHorizontalTangent
                         * mMinimumHorizontalTangent;
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index a747f16..d201ade 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -154,11 +154,11 @@
     public static final int DENSITY_DEVICE_STABLE = getDeviceDensity();
 
     /**
-     * The absolute width of the display in pixels.
+     * The absolute width of the available display size in pixels.
      */
     public int widthPixels;
     /**
-     * The absolute height of the display in pixels.
+     * The absolute height of the available display size in pixels.
      */
     public int heightPixels;
     /**
diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java
index 98aaa81..bd00aba 100644
--- a/core/java/android/util/TypedValue.java
+++ b/core/java/android/util/TypedValue.java
@@ -17,6 +17,7 @@
 package android.util;
 
 import android.annotation.AnyRes;
+import android.content.pm.ActivityInfo.Config;
 
 /**
  * Container for a dynamically typed data value.  Primarily used with
@@ -183,9 +184,11 @@
     @AnyRes
     public int resourceId;
 
-    /** If Value came from a resource, these are the configurations for which
-     *  its contents can change. */
-    public int changingConfigurations = -1;
+    /**
+     * If the value came from a resource, these are the configurations for
+     * which its contents can change.
+     */
+    public @Config int changingConfigurations = -1;
 
     /**
      * If the Value came from a resource, this holds the corresponding pixel density.
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index 60c7270..dcf987b 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -84,8 +84,19 @@
             if (fileSize > Integer.MAX_VALUE) {
                 return false;
             }
-            MappedByteBuffer apkContents =
-                    apk.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
+            MappedByteBuffer apkContents;
+            try {
+                apkContents = apk.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
+            } catch (IOException e) {
+                if (e.getCause() instanceof OutOfMemoryError) {
+                    // TODO: Remove this temporary workaround once verifying large APKs is
+                    // supported. Very large APKs cannot be memory-mapped. This verification code
+                    // needs to change to use a different approach for verifying such APKs.
+                    return false; // Pretend that this APK does not have a v2 signature.
+                } else {
+                    throw new IOException("Failed to memory-map APK", e);
+                }
+            }
             // ZipUtils and APK Signature Scheme v2 verifier expect little-endian byte order.
             apkContents.order(ByteOrder.LITTLE_ENDIAN);
 
@@ -134,11 +145,26 @@
         if (fileSize > Integer.MAX_VALUE) {
             throw new IOException("File too large: " + apk.length() + " bytes");
         }
-        MappedByteBuffer apkContents =
-                apk.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
-        // Attempt to preload the contents into memory for faster overall verification (v2 and
-        // older) at the expense of somewhat increased latency for rejecting malformed APKs.
-        apkContents.load();
+        MappedByteBuffer apkContents;
+        try {
+            apkContents = apk.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
+            // Attempt to preload the contents into memory for faster overall verification (v2 and
+            // older) at the expense of somewhat increased latency for rejecting malformed APKs.
+            apkContents.load();
+        } catch (IOException e) {
+            if (e.getCause() instanceof OutOfMemoryError) {
+                // TODO: Remove this temporary workaround once verifying large APKs is supported.
+                // Very large APKs cannot be memory-mapped. This verification code needs to change
+                // to use a different approach for verifying such APKs.
+                // This workaround pretends that this APK does not have a v2 signature. This works
+                // fine provided the APK is not actually v2-signed. If the APK is v2 signed, v2
+                // signature stripping protection inside v1 signature verification code will reject
+                // this APK.
+                throw new SignatureNotFoundException("Failed to memory-map APK", e);
+            } else {
+                throw new IOException("Failed to memory-map APK", e);
+            }
+        }
         return verify(apkContents);
     }
 
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 1269ad9..22d5ed8 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.IntDef;
 import android.annotation.RequiresPermission;
 import android.content.Context;
 import android.content.res.CompatibilityInfo;
@@ -31,6 +32,8 @@
 import android.util.DisplayMetrics;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 
 import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM;
@@ -715,6 +718,14 @@
     }
 
     /**
+     * Returns the display's HDR capabilities.
+     * @hide
+     */
+    public HdrCapabilities getHdrCapabilities() {
+        return new HdrCapabilities();
+    }
+
+    /**
      * Gets the supported color transforms of this device.
      * @hide
      */
@@ -762,14 +773,23 @@
 
     /**
      * Gets display metrics that describe the size and density of this display.
-     * <p>
-     * The size is adjusted based on the current rotation of the display.
-     * </p><p>
      * The size returned by this method does not necessarily represent the
-     * actual raw size (native resolution) of the display.  The returned size may
-     * be adjusted to exclude certain system decor elements that are always visible.
-     * It may also be scaled to provide compatibility with older applications that
+     * actual raw size (native resolution) of the display.
+     * <p>
+     * 1. The returned size may be adjusted to exclude certain system decor elements
+     * that are always visible.
+     * </p><p>
+     * 2. It may be scaled to provide compatibility with older applications that
      * were originally designed for smaller displays.
+     * </p><p>
+     * 3. It can be different depending on the WindowManager to which the display belongs.
+     * <pre>
+     * - If requested from non-Activity context (e.g. Application context via
+     * {@code (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE)})
+     * metrics will report real size of the display based on current rotation.
+     * - If requested from activity resulting metrics will correspond to current window metrics.
+     * In this case the size can be smaller than physical size in multi-window mode.
+     * </pre>
      * </p>
      *
      * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
@@ -807,7 +827,7 @@
      * The size is adjusted based on the current rotation of the display.
      * </p><p>
      * The real size may be smaller than the physical size of the screen when the
-     * window manager is emulating a smaller display (using adb shell am display-size).
+     * window manager is emulating a smaller display (using adb shell wm size).
      * </p>
      *
      * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
@@ -816,8 +836,7 @@
         synchronized (this) {
             updateDisplayInfoLocked();
             mDisplayInfo.getLogicalMetrics(outMetrics,
-                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO,
-                    mDisplayAdjustments.getConfiguration());
+                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
         }
     }
 
@@ -1104,6 +1123,117 @@
     }
 
     /**
+     * Encapsulates the HDR capabilities of a given display.
+     * For example, what HDR types it supports and details about the desired luminance data.
+     * <p>You can get an instance for a given {@link Display} object with
+     * {@link Display#getHdrCapabilities getHdrCapabilities()}.
+     * @hide
+     */
+    public static final class HdrCapabilities implements Parcelable {
+        /**
+         * Invalid luminance value.
+         */
+        public static final float INVALID_LUMINANCE = -1;
+        /**
+         * Dolby Vision high dynamic range (HDR) display.
+         */
+        public static final int HDR_TYPE_DOLBY_VISION = 1;
+        /**
+         * HDR10 display.
+         */
+        public static final int HDR_TYPE_HDR10 = 2;
+        /**
+         * Hybrid Log-Gamma HDR display.
+         */
+        public static final int HDR_TYPE_HLG = 3;
+
+        @IntDef({
+            HDR_TYPE_DOLBY_VISION,
+            HDR_TYPE_HDR10,
+            HDR_TYPE_HLG,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface HdrType {}
+
+        private @HdrType int[] mSupportedHdrTypes = new int[0];
+        private float mMaxLuminance = INVALID_LUMINANCE;
+        private float mMaxAverageLuminance = INVALID_LUMINANCE;
+        private float mMinLuminance = INVALID_LUMINANCE;
+
+        public HdrCapabilities() {
+        }
+
+        /**
+         * Gets the supported HDR types of this display.
+         * Returns empty array if HDR is not supported by the display.
+         */
+        public @HdrType int[] getSupportedHdrTypes() {
+            return mSupportedHdrTypes;
+        }
+        /**
+         * Returns the desired content max luminance data in cd/m2 for this display.
+         */
+        public float getDesiredMaxLuminance() {
+            return mMaxLuminance;
+        }
+        /**
+         * Returns the desired content max frame-average luminance data in cd/m2 for this display.
+         */
+        public float getDesiredMaxAverageLuminance() {
+            return mMaxAverageLuminance;
+        }
+        /**
+         * Returns the desired content min luminance data in cd/m2 for this display.
+         */
+        public float getDesiredMinLuminance() {
+            return mMinLuminance;
+        }
+
+        public static final Creator<HdrCapabilities> CREATOR = new Creator<HdrCapabilities>() {
+            @Override
+            public HdrCapabilities createFromParcel(Parcel source) {
+                return new HdrCapabilities(source);
+            }
+
+            @Override
+            public HdrCapabilities[] newArray(int size) {
+                return new HdrCapabilities[size];
+            }
+        };
+
+        private HdrCapabilities(Parcel source) {
+            readFromParcel(source);
+        }
+
+        public void readFromParcel(Parcel source) {
+            int types = source.readInt();
+            mSupportedHdrTypes = new int[types];
+            for (int i = 0; i < types; ++i) {
+                mSupportedHdrTypes[i] = source.readInt();
+            }
+            mMaxLuminance = source.readFloat();
+            mMaxAverageLuminance = source.readFloat();
+            mMinLuminance = source.readFloat();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(mSupportedHdrTypes.length);
+            for (int i = 0; i < mSupportedHdrTypes.length; ++i) {
+                dest.writeInt(mSupportedHdrTypes[i]);
+            }
+            dest.writeFloat(mMaxLuminance);
+            dest.writeFloat(mMaxAverageLuminance);
+            dest.writeFloat(mMinLuminance);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+    }
+
+    /**
      * A color transform supported by a given display.
      *
      * @see Display#getSupportedColorTransforms()
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 8048301..d8b7421 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -193,8 +193,7 @@
     boolean isKeyguardSecure();
     boolean inKeyguardRestrictedInputMode();
     void dismissKeyguard();
-    void keyguardGoingAway(boolean disableWindowAnimations,
-            boolean keyguardGoingToNotificationShade);
+    void keyguardGoingAway(int flags);
 
     void closeSystemDialogs(String reason);
 
@@ -363,6 +362,12 @@
     void setDockedStackResizing(boolean resizing);
 
     /**
+     * Sets the region the user can touch the divider. This region will be excluded from the region
+     * which is used to cause a focus switch when dispatching touch.
+     */
+    void setDockedStackDividerTouchRegion(in Rect touchableRegion);
+
+    /**
      * Registers a listener that will be called when the dock divider changes its visibility or when
      * the docked stack gets added/removed.
      */
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 9bd3df0..a7bf73a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -84,7 +84,6 @@
 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
 import android.view.AccessibilityIterators.TextSegmentIterator;
 import android.view.AccessibilityIterators.WordTextSegmentIterator;
-import android.view.ViewGroup.LayoutParams;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityEventSource;
 import android.view.accessibility.AccessibilityManager;
@@ -10151,19 +10150,6 @@
      *                   {@link #INVISIBLE} or {@link #GONE}.
      */
     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
-        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
-        if (visible && mAttachInfo != null) {
-            initialAwakenScrollBars();
-        }
-
-        final Drawable dr = mBackground;
-        if (dr != null && visible != dr.isVisible()) {
-            dr.setVisible(visible, false);
-        }
-        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
-        if (fg != null && visible != fg.isVisible()) {
-            fg.setVisible(visible, false);
-        }
     }
 
     /**
@@ -10220,6 +10206,46 @@
     }
 
     /**
+     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
+     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
+     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
+     *
+     * @param isVisible true if this view's visibility to the user is uninterrupted by its
+     *                  ancestors or by window visibility
+     * @return true if this view is visible to the user, not counting clipping or overlapping
+     */
+    @Visibility boolean dispatchVisibilityAggregated(boolean isVisible) {
+        final boolean thisVisible = getVisibility() == VISIBLE;
+        if (thisVisible) {
+            onVisibilityAggregated(isVisible);
+        }
+        return thisVisible && isVisible;
+    }
+
+    /**
+     * Called when the user-visibility of this View is potentially affected by a change
+     * to this view itself, an ancestor view or the window this view is attached to.
+     *
+     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
+     *                  and this view's window is also visible
+     */
+    @CallSuper
+    public void onVisibilityAggregated(boolean isVisible) {
+        if (isVisible && mAttachInfo != null) {
+            initialAwakenScrollBars();
+        }
+
+        final Drawable dr = mBackground;
+        if (dr != null && isVisible != dr.isVisible()) {
+            dr.setVisible(isVisible, false);
+        }
+        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
+        if (fg != null && isVisible != fg.isVisible()) {
+            fg.setVisible(isVisible, false);
+        }
+    }
+
+    /**
      * Returns the current visibility of the window this view is attached to
      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
      *
@@ -11336,6 +11362,16 @@
 
             if (mAttachInfo != null) {
                 dispatchVisibilityChanged(this, newVisibility);
+
+                // Aggregated visibility changes are dispatched to attached views
+                // in visible windows where the parent is currently shown/drawn
+                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
+                // discounting clipping or overlapping. This makes it a good place
+                // to change animation states.
+                if (mParent != null && getWindowVisibility() == VISIBLE &&
+                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
+                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
+                }
                 notifySubtreeAccessibilityStateChangedIfNeeded();
             }
         }
@@ -15246,6 +15282,11 @@
         int vis = info.mWindowVisibility;
         if (vis != GONE) {
             onWindowVisibilityChanged(vis);
+            if (isShown()) {
+                // Calling onVisibilityChanged directly here since the subtree will also
+                // receive dispatchAttachedToWindow and this same call
+                onVisibilityAggregated(vis == VISIBLE);
+            }
         }
 
         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
@@ -15266,6 +15307,11 @@
             int vis = info.mWindowVisibility;
             if (vis != GONE) {
                 onWindowVisibilityChanged(GONE);
+                if (isShown()) {
+                    // Invoking onVisibilityAggregated directly here since the subtree
+                    // will also receive detached from window
+                    onVisibilityAggregated(false);
+                }
             }
         }
 
@@ -17505,7 +17551,7 @@
      *        {@link SystemClock#uptimeMillis} timebase.
      */
     @Override
-    public void scheduleDrawable(Drawable who, Runnable what, long when) {
+    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
         if (verifyDrawable(who) && what != null) {
             final long delay = when - SystemClock.uptimeMillis();
             if (mAttachInfo != null) {
@@ -17527,7 +17573,7 @@
      * @param what the action to cancel
      */
     @Override
-    public void unscheduleDrawable(Drawable who, Runnable what) {
+    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
         if (verifyDrawable(who) && what != null) {
             if (mAttachInfo != null) {
                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
@@ -17637,7 +17683,7 @@
      * @see #drawableStateChanged()
      */
     @CallSuper
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         // Avoid verifying the scroll bar drawable so that we don't end up in
         // an invalidation loop. This effectively prevents the scroll bar
         // drawable from triggering invalidations and scheduling runnables.
@@ -17953,9 +17999,12 @@
 
         /*
          * Regardless of whether we're setting a new background or not, we want
-         * to clear the previous drawable.
+         * to clear the previous drawable. setVisible first while we still have the callback set.
          */
         if (mBackground != null) {
+            if (isAttachedToWindow()) {
+                mBackground.setVisible(false, false);
+            }
             mBackground.setCallback(null);
             unscheduleDrawable(mBackground);
         }
@@ -17994,12 +18043,19 @@
                 requestLayout = true;
             }
 
+            // Set mBackground before we set this as the callback and start making other
+            // background drawable state change calls. In particular, the setVisible call below
+            // can result in drawables attempting to start animations or otherwise invalidate,
+            // which requires the view set as the callback (us) to recognize the drawable as
+            // belonging to it as per verifyDrawable.
+            mBackground = background;
             background.setCallback(this);
             if (background.isStateful()) {
                 background.setState(getDrawableState());
             }
-            background.setVisible(getVisibility() == VISIBLE, false);
-            mBackground = background;
+            if (isAttachedToWindow()) {
+                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
+            }
 
             applyBackgroundTint();
 
@@ -18178,6 +18234,9 @@
         }
 
         if (mForegroundInfo.mDrawable != null) {
+            if (isAttachedToWindow()) {
+                mForegroundInfo.mDrawable.setVisible(false, false);
+            }
             mForegroundInfo.mDrawable.setCallback(null);
             unscheduleDrawable(mForegroundInfo.mDrawable);
         }
@@ -18194,6 +18253,9 @@
                 foreground.setState(getDrawableState());
             }
             applyForegroundTint();
+            if (isAttachedToWindow()) {
+                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
+            }
         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
             mPrivateFlags |= PFLAG_SKIP_DRAW;
         }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c54ce80..aa11e3f 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1291,6 +1291,22 @@
     }
 
     @Override
+    boolean dispatchVisibilityAggregated(boolean isVisible) {
+        isVisible = super.dispatchVisibilityAggregated(isVisible);
+        final int count = mChildrenCount;
+        final View[] children = mChildren;
+        for (int i = 0; i < count; i++) {
+            // Only dispatch to visible children. Not visible children and their subtrees already
+            // know that they aren't visible and that's not going to change as a result of
+            // whatever triggered this dispatch.
+            if (children[i].getVisibility() == VISIBLE) {
+                children[i].dispatchVisibilityAggregated(isVisible);
+            }
+        }
+        return isVisible;
+    }
+
+    @Override
     public void dispatchConfigurationChanged(Configuration newConfig) {
         super.dispatchConfigurationChanged(newConfig);
         final int count = mChildrenCount;
@@ -1382,6 +1398,13 @@
             if (mIsInterestedInDrag) {
                 retval = true;
             }
+
+            if (!retval) {
+                // Neither us nor any of our children are interested in this drag, so stop tracking
+                // the current drag event.
+                mCurrentDragStartEvent.recycle();
+                mCurrentDragStartEvent = null;
+            }
         } break;
 
         case DragEvent.ACTION_DRAG_ENDED: {
@@ -5357,9 +5380,6 @@
     void offsetRectBetweenParentAndChild(View descendant, Rect rect,
             boolean offsetFromChildToParent, boolean clipToBounds) {
 
-        final RectF rectF = mAttachInfo != null ? mAttachInfo.mTmpTransformRect1 : new RectF();
-        final Matrix inverse = mAttachInfo != null ? mAttachInfo.mTmpMatrix : new Matrix();
-
         // already in the same coord system :)
         if (descendant == this) {
             return;
@@ -5373,16 +5393,8 @@
                 && (theParent != this)) {
 
             if (offsetFromChildToParent) {
-                rect.offset(-descendant.mScrollX, -descendant.mScrollY);
-
-                if (!descendant.hasIdentityMatrix()) {
-                    rectF.set(rect);
-                    descendant.getMatrix().mapRect(rectF);
-                    rectF.roundOut(rect);
-                }
-
-                rect.offset(descendant.mLeft, descendant.mTop);
-
+                rect.offset(descendant.mLeft - descendant.mScrollX,
+                        descendant.mTop - descendant.mScrollY);
                 if (clipToBounds) {
                     View p = (View) theParent;
                     boolean intersected = rect.intersect(0, 0, p.mRight - p.mLeft,
@@ -5400,16 +5412,8 @@
                         rect.setEmpty();
                     }
                 }
-                rect.offset(-descendant.mLeft, -descendant.mTop);
-
-                if (!descendant.hasIdentityMatrix()) {
-                    descendant.getMatrix().invert(inverse);
-                    rectF.set(rect);
-                    inverse.mapRect(rectF);
-                    rectF.roundOut(rect);
-                }
-
-                rect.offset(descendant.mScrollX, descendant.mScrollY);
+                rect.offset(descendant.mScrollX - descendant.mLeft,
+                        descendant.mScrollY - descendant.mTop);
             }
 
             descendant = (View) theParent;
@@ -5420,26 +5424,11 @@
         // to get into our coordinate space
         if (theParent == this) {
             if (offsetFromChildToParent) {
-                rect.offset(-descendant.mScrollX, -descendant.mScrollY);
-
-                if (!descendant.hasIdentityMatrix()) {
-                    rectF.set(rect);
-                    descendant.getMatrix().mapRect(rectF);
-                    rectF.roundOut(rect);
-                }
-
-                rect.offset(descendant.mLeft, descendant.mTop);
+                rect.offset(descendant.mLeft - descendant.mScrollX,
+                        descendant.mTop - descendant.mScrollY);
             } else {
-                rect.offset(-descendant.mLeft, -descendant.mTop);
-
-                if (!descendant.hasIdentityMatrix()) {
-                    descendant.getMatrix().invert(inverse);
-                    rectF.set(rect);
-                    inverse.mapRect(rectF);
-                    rectF.roundOut(rect);
-                }
-
-                rect.offset(descendant.mScrollX, descendant.mScrollY);
+                rect.offset(descendant.mScrollX - descendant.mLeft,
+                        descendant.mScrollY - descendant.mTop);
             }
         } else {
             throw new IllegalArgumentException("parameter must be a descendant of this view");
diff --git a/core/java/android/view/ViewGroupOverlay.java b/core/java/android/view/ViewGroupOverlay.java
index 16afc5d..c2807ba 100644
--- a/core/java/android/view/ViewGroupOverlay.java
+++ b/core/java/android/view/ViewGroupOverlay.java
@@ -15,6 +15,7 @@
  */
 package android.view;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 
@@ -37,7 +38,7 @@
     }
 
     /**
-     * Adds a View to the overlay. The bounds of the added view should be
+     * Adds a {@code View} to the overlay. The bounds of the added view should be
      * relative to the host view. Any view added to the overlay should be
      * removed when it is no longer needed or no longer visible.
      *
@@ -54,23 +55,32 @@
      * and 200 pixels down from the origin of the overlay's
      * host view, then the view will be offset by (100, 200).</p>
      *
-     * @param view The View to be added to the overlay. The added view will be
+     * <p>{@code View}s added with this API will be drawn in the order they were
+     * added. Drawing of the overlay views will happen before drawing of any of the
+     * {@code Drawable}s added with {@link #add(Drawable)} API even if a call to
+     * this API happened after the call to {@link #add(Drawable)}.</p>
+     *
+     * <p>Passing <code>null</code> parameter will result in an
+     * {@link IllegalArgumentException} being thrown.</p>
+     *
+     * @param view The {@code View} to be added to the overlay. The added view will be
      * drawn when the overlay is drawn.
      * @see #remove(View)
      * @see ViewOverlay#add(Drawable)
      */
-    public void add(View view) {
+    public void add(@NonNull View view) {
         mOverlayViewGroup.add(view);
     }
 
     /**
-     * Removes the specified View from the overlay.
+     * Removes the specified {@code View} from the overlay. Passing <code>null</code> parameter
+     * will result in an {@link IllegalArgumentException} being thrown.
      *
-     * @param view The View to be removed from the overlay.
+     * @param view The {@code View} to be removed from the overlay.
      * @see #add(View)
      * @see ViewOverlay#remove(Drawable)
      */
-    public void remove(View view) {
+    public void remove(@NonNull View view) {
         mOverlayViewGroup.remove(view);
     }
 }
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index 5e5ef29..b770bd5 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -16,6 +16,7 @@
 package android.view;
 
 import android.animation.LayoutTransition;
+import android.annotation.NonNull;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Rect;
@@ -59,25 +60,30 @@
     }
 
     /**
-     * Adds a Drawable to the overlay. The bounds of the drawable should be relative to
+     * Adds a {@link Drawable} to the overlay. The bounds of the drawable should be relative to
      * the host view. Any drawable added to the overlay should be removed when it is no longer
-     * needed or no longer visible.
+     * needed or no longer visible. Adding an already existing {@link Drawable}
+     * is a no-op. Passing <code>null</code> parameter will result in an
+     * {@link IllegalArgumentException} being thrown.
      *
-     * @param drawable The Drawable to be added to the overlay. This drawable will be
-     * drawn when the view redraws its overlay.
+     * @param drawable The {@link Drawable} to be added to the overlay. This drawable will be
+     * drawn when the view redraws its overlay. {@link Drawable}s will be drawn in the order that
+     * they were added.
      * @see #remove(Drawable)
      */
-    public void add(Drawable drawable) {
+    public void add(@NonNull Drawable drawable) {
         mOverlayViewGroup.add(drawable);
     }
 
     /**
-     * Removes the specified Drawable from the overlay.
+     * Removes the specified {@link Drawable} from the overlay. Removing a {@link Drawable} that was
+     * not added with {@link #add(Drawable)} is a no-op. Passing <code>null</code> parameter will
+     * result in an {@link IllegalArgumentException} being thrown.
      *
-     * @param drawable The Drawable to be removed from the overlay.
+     * @param drawable The {@link Drawable} to be removed from the overlay.
      * @see #add(Drawable)
      */
-    public void remove(Drawable drawable) {
+    public void remove(@NonNull Drawable drawable) {
         mOverlayViewGroup.remove(drawable);
     }
 
@@ -119,7 +125,7 @@
          * The View for which this is an overlay. Invalidations of the overlay are redirected to
          * this host view.
          */
-        View mHostView;
+        final View mHostView;
 
         /**
          * The set of drawables to draw when the overlay is rendered.
@@ -137,10 +143,12 @@
             mRenderNode.setLeftTopRightBottom(0, 0, mRight, mBottom);
         }
 
-        public void add(Drawable drawable) {
+        public void add(@NonNull Drawable drawable) {
+            if (drawable == null) {
+                throw new IllegalArgumentException("drawable must be non-null");
+            }
             if (mDrawables == null) {
-
-                mDrawables = new ArrayList<Drawable>();
+                mDrawables = new ArrayList<>();
             }
             if (!mDrawables.contains(drawable)) {
                 // Make each drawable unique in the overlay; can't add it more than once
@@ -150,7 +158,10 @@
             }
         }
 
-        public void remove(Drawable drawable) {
+        public void remove(@NonNull Drawable drawable) {
+            if (drawable == null) {
+                throw new IllegalArgumentException("drawable must be non-null");
+            }
             if (mDrawables != null) {
                 mDrawables.remove(drawable);
                 invalidate(drawable.getBounds());
@@ -159,11 +170,15 @@
         }
 
         @Override
-        protected boolean verifyDrawable(Drawable who) {
+        protected boolean verifyDrawable(@NonNull Drawable who) {
             return super.verifyDrawable(who) || (mDrawables != null && mDrawables.contains(who));
         }
 
-        public void add(View child) {
+        public void add(@NonNull View child) {
+            if (child == null) {
+                throw new IllegalArgumentException("view must be non-null");
+            }
+
             if (child.getParent() instanceof ViewGroup) {
                 ViewGroup parent = (ViewGroup) child.getParent();
                 if (parent != mHostView && parent.getParent() != null &&
@@ -190,13 +205,20 @@
             super.addView(child);
         }
 
-        public void remove(View view) {
+        public void remove(@NonNull View view) {
+            if (view == null) {
+                throw new IllegalArgumentException("view must be non-null");
+            }
+
             super.removeView(view);
         }
 
         public void clear() {
             removeAllViews();
             if (mDrawables != null) {
+                for (Drawable drawable : mDrawables) {
+                    drawable.setCallback(null);
+                }
                 mDrawables.clear();
             }
         }
@@ -210,7 +232,7 @@
         }
 
         @Override
-        public void invalidateDrawable(Drawable drawable) {
+        public void invalidateDrawable(@NonNull Drawable drawable) {
             invalidate(drawable.getBounds());
         }
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f7405e2..a2295ce 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1472,6 +1472,7 @@
         if (viewVisibilityChanged) {
             mAttachInfo.mWindowVisibility = viewVisibility;
             host.dispatchWindowVisibilityChanged(viewVisibility);
+            host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE);
             if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
                 endDragResizing();
                 destroyHardwareResources();
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 9f05990..63f3744 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -566,8 +566,8 @@
          * @param data The data list to populate with shortcuts.
          * @param menu The current menu, which may be null.
          */
-        public void onProvideKeyboardShortcuts(
-                List<KeyboardShortcutGroup> data, @Nullable Menu menu);
+        default public void onProvideKeyboardShortcuts(
+                List<KeyboardShortcutGroup> data, @Nullable Menu menu) { };
     }
 
     /** @hide */
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index a1cbc1d..887cc3a 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -170,7 +170,7 @@
                     sWindowManagerService = getWindowManagerService();
                     ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
                 } catch (RemoteException e) {
-                    Log.e(TAG, "Failed to get WindowManagerService, cannot set animator scale", e);
+                    throw e.rethrowFromSystemServer();
                 }
             }
             return sWindowManagerService;
@@ -192,7 +192,7 @@
                             },
                             imm.getClient(), imm.getInputContext());
                 } catch (RemoteException e) {
-                    Log.e(TAG, "Failed to open window session", e);
+                    throw e.rethrowFromSystemServer();
                 }
             }
             return sWindowSession;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index b011414..c1392fe 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -91,6 +91,11 @@
     public final static int FLAG_INTERACTIVE = 0x20000000;
     public final static int FLAG_PASS_TO_USER = 0x40000000;
 
+    // Flags for IActivityManager.keyguardGoingAway()
+    public final static int KEYGUARD_GOING_AWAY_FLAG_TO_SHADE = 1 << 0;
+    public final static int KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS = 1 << 1;
+    public final static int KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER = 1 << 2;
+
     // Flags used for indicating whether the internal and/or external input devices
     // of some type are available.
     public final static int PRESENCE_INTERNAL = 1 << 0;
@@ -405,6 +410,12 @@
          *         not attached to any stack.
          */
         int getStackId();
+
+        /**
+         * Returns true if the window is current in multi-windowing mode. i.e. it shares the
+         * screen with other application windows.
+         */
+        public boolean inMultiWindowMode();
     }
 
     /**
diff --git a/core/java/android/view/animation/BaseInterpolator.java b/core/java/android/view/animation/BaseInterpolator.java
index 9c0014c..a78fa1e 100644
--- a/core/java/android/view/animation/BaseInterpolator.java
+++ b/core/java/android/view/animation/BaseInterpolator.java
@@ -16,22 +16,24 @@
 
 package android.view.animation;
 
+import android.content.pm.ActivityInfo.Config;
+
 /**
  * An abstract class which is extended by default interpolators.
  */
 abstract public class BaseInterpolator implements Interpolator {
-    private int mChangingConfiguration;
+    private @Config int mChangingConfiguration;
     /**
      * @hide
      */
-    public int getChangingConfiguration() {
+    public @Config int getChangingConfiguration() {
         return mChangingConfiguration;
     }
 
     /**
      * @hide
      */
-    void setChangingConfiguration(int changingConfiguration) {
+    void setChangingConfiguration(@Config int changingConfiguration) {
         mChangingConfiguration = changingConfiguration;
     }
 }
diff --git a/core/java/android/view/textservice/SpellCheckerSubtype.java b/core/java/android/view/textservice/SpellCheckerSubtype.java
index df33698..35d3bf9 100644
--- a/core/java/android/view/textservice/SpellCheckerSubtype.java
+++ b/core/java/android/view/textservice/SpellCheckerSubtype.java
@@ -50,7 +50,10 @@
     private static final String TAG = SpellCheckerSubtype.class.getSimpleName();
     private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
     private static final String EXTRA_VALUE_KEY_VALUE_SEPARATOR = "=";
-    private static final int SUBTYPE_ID_NONE = 0;
+    /**
+     * @hide
+     */
+    public static final int SUBTYPE_ID_NONE = 0;
     private static final String SUBTYPE_LANGUAGE_TAG_NONE = "";
 
     private final int mSubtypeId;
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 3d72260..0751ab0 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -106,6 +106,9 @@
     public static final int LIBLOAD_WEBVIEW_BEING_REPLACED = 8;
     public static final int LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN = 9;
 
+    // error for namespace lookup
+    public static final int LIBLOAD_FAILED_TO_FIND_NAMESPACE = 10;
+
     private static String getWebViewPreparationErrorReason(int error) {
         switch (error) {
             case LIBLOAD_FAILED_WAITING_FOR_RELRO:
@@ -239,7 +242,8 @@
      * Load the native library for the given package name iff that package
      * name is the same as the one providing the webview.
      */
-    public static int loadWebViewNativeLibraryFromPackage(String packageName) {
+    public static int loadWebViewNativeLibraryFromPackage(String packageName,
+                                                          ClassLoader clazzLoader) {
         int ret = waitForProviderAndSetPackageInfo();
         if (ret != LIBLOAD_SUCCESS) {
             return ret;
@@ -247,7 +251,7 @@
         if (!sPackageInfo.packageName.equals(packageName))
             return LIBLOAD_WRONG_PACKAGE_NAME;
 
-        return loadNativeLibrary();
+        return loadNativeLibrary(clazzLoader);
     }
 
     static WebViewFactoryProvider getProvider() {
@@ -333,15 +337,16 @@
                 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
             }
 
-            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
-            loadNativeLibrary();
-            Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
-
             Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()");
             try {
                 initialApplication.getAssets().addAssetPathAsSharedLibrary(
                         webViewContext.getApplicationInfo().sourceDir);
                 ClassLoader clazzLoader = webViewContext.getClassLoader();
+
+                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
+                loadNativeLibrary(clazzLoader);
+                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
+
                 Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
                 try {
                     return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY,
@@ -633,7 +638,7 @@
     }
 
     // Assumes that we have waited for relro creation and set sPackageInfo
-    private static int loadNativeLibrary() {
+    private static int loadNativeLibrary(ClassLoader clazzLoader) {
         if (!sAddressSpaceReserved) {
             Log.e(LOGTAG, "can't load with relro file; address space not reserved");
             return LIBLOAD_ADDRESS_SPACE_NOT_RESERVED;
@@ -641,9 +646,10 @@
 
         String[] args = getWebViewNativeLibraryPaths(sPackageInfo);
         int result = nativeLoadWithRelroFile(args[0] /* path32 */,
-                                                 args[1] /* path64 */,
-                                                 CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
-                                                 CHROMIUM_WEBVIEW_NATIVE_RELRO_64);
+                                             args[1] /* path64 */,
+                                             CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
+                                             CHROMIUM_WEBVIEW_NATIVE_RELRO_64,
+                                             clazzLoader);
         if (result != LIBLOAD_SUCCESS) {
             Log.w(LOGTAG, "failed to load with relro file, proceeding without");
         } else if (DEBUG) {
@@ -672,5 +678,6 @@
     private static native boolean nativeCreateRelroFile(String lib32, String lib64,
                                                         String relro32, String relro64);
     private static native int nativeLoadWithRelroFile(String lib32, String lib64,
-                                                          String relro32, String relro64);
+                                                      String relro32, String relro64,
+                                                      ClassLoader clazzLoader);
 }
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index d2aef0a..7cbe8de 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2864,7 +2864,7 @@
     }
 
     @Override
-    public boolean verifyDrawable(Drawable dr) {
+    public boolean verifyDrawable(@NonNull Drawable dr) {
         return mSelector == dr || super.verifyDrawable(dr);
     }
 
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 34f3a47..878a9eb 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.R;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -485,7 +486,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return who == mThumb || who == mTickMark || super.verifyDrawable(who);
     }
 
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 9f94005..df506ca 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -308,7 +308,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return who == mCheckMarkDrawable || super.verifyDrawable(who);
     }
 
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index b19fe17..5d7585f 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -474,7 +474,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return super.verifyDrawable(who) || who == mButtonDrawable;
     }
 
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index f5840dc..8ce2f9c 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -282,7 +282,7 @@
     public CharSequence getPageTitle(int position) {
         final SimpleMonthView v = mItems.get(position).calendar;
         if (v != null) {
-            return v.getTitle();
+            return v.getMonthYearLabel();
         }
         return null;
     }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 6959137..4bcb406 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -18,6 +18,7 @@
 
 import android.R;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.PendingIntent;
 import android.app.PendingIntent.CanceledException;
@@ -216,6 +217,7 @@
     boolean mInBatchEditControllers;
     boolean mShowSoftInputOnFocus = true;
     private boolean mPreserveSelection;
+    private boolean mRestartActionModeOnNextRefresh;
     boolean mTemporaryDetach;
 
     boolean mIsBeingLongClicked;
@@ -290,7 +292,6 @@
     boolean mIsInsertionActionModeStartPending = false;
 
     private final SuggestionHelper mSuggestionHelper = new SuggestionHelper();
-    private SuggestionInfo[] mSuggestionInfosInContextMenu;
 
     Editor(TextView textView) {
         mTextView = textView;
@@ -381,9 +382,8 @@
         updateSpellCheckSpans(0, mTextView.getText().length(),
                 true /* create the spell checker if needed */);
 
-        if (mTextView.getSelectionStart() != mTextView.getSelectionEnd()) {
-            // We had an active selection from before, start the selection mode.
-            startSelectionActionMode();
+        if (mTextView.hasSelection()) {
+            refreshTextActionMode();
         }
 
         getPositionListener().addSubscriber(mCursorAnchorInfoNotifier, true);
@@ -926,7 +926,8 @@
     }
 
     void onLocaleChanged() {
-        // Will be re-created on demand in getWordIterator with the proper new locale
+        // Will be re-created on demand in getWordIterator and getWordIteratorWithText with the
+        // proper new locale
         mWordIterator = null;
         mWordIteratorWithText = null;
     }
@@ -1081,6 +1082,10 @@
     }
 
     private void startDragAndDrop() {
+        // TODO: Fix drag and drop in full screen extracted mode.
+        if (mTextView.isInExtractedMode()) {
+            return;
+        }
         final int start = mTextView.getSelectionStart();
         final int end = mTextView.getSelectionEnd();
         CharSequence selectedText = mTextView.getTransformedText(start, end);
@@ -1283,7 +1288,7 @@
             }
             final InputMethodManager imm = InputMethodManager.peekInstance();
             if (mTextView.hasSelection() && !extractedTextModeWillBeStarted()) {
-                startSelectionActionMode();
+                refreshTextActionMode();
             }
         } else {
             if (mBlink != null) {
@@ -1846,6 +1851,7 @@
 
     void refreshTextActionMode() {
         if (extractedTextModeWillBeStarted()) {
+            mRestartActionModeOnNextRefresh = false;
             return;
         }
         final boolean hasSelection = mTextView.hasSelection();
@@ -1854,12 +1860,19 @@
         if ((selectionController != null && selectionController.isCursorBeingModified())
                 || (insertionController != null && insertionController.isCursorBeingModified())) {
             // ActionMode should be managed by the currently active cursor controller.
+            mRestartActionModeOnNextRefresh = false;
             return;
         }
         if (hasSelection) {
-            if (mTextActionMode == null || selectionController == null
-                    || !selectionController.isActive()) {
-                // Avoid dismissing the selection if it exists.
+            hideInsertionPointCursorController();
+            if (mTextActionMode == null) {
+                if (mRestartActionModeOnNextRefresh || mTextView.isInExtractedMode()) {
+                    // To avoid distraction, newly start action mode only when selection action
+                    // mode is being restarted or in full screen extracted mode.
+                    startSelectionActionMode();
+                }
+            } else if (selectionController == null || !selectionController.isActive()) {
+                // Insertion action mode is active. Avoid dismissing the selection.
                 stopTextActionModeWithPreservingSelection();
                 startSelectionActionMode();
             } else {
@@ -1874,6 +1887,7 @@
                 mTextActionMode.invalidateContentRect();
             }
         }
+        mRestartActionModeOnNextRefresh = false;
     }
 
     /**
@@ -1904,11 +1918,12 @@
      *
      * @return true if the selection mode was actually started.
      */
-    private boolean startSelectionActionMode() {
+    boolean startSelectionActionMode() {
         boolean selectionStarted = startSelectionActionModeInternal();
         if (selectionStarted) {
             getSelectionController().show();
         }
+        mRestartActionModeOnNextRefresh = false;
         return selectionStarted;
     }
 
@@ -2112,6 +2127,9 @@
     }
 
     private void stopTextActionModeWithPreservingSelection() {
+        if (mTextActionMode != null) {
+            mRestartActionModeOnNextRefresh = true;
+        }
         mPreserveSelection = true;
         stopTextActionMode();
         mPreserveSelection = false;
@@ -2453,21 +2471,24 @@
         }
 
         if (shouldOfferToShowSuggestions()) {
-            if (mSuggestionInfosInContextMenu == null) {
-                mSuggestionInfosInContextMenu =
-                        new SuggestionInfo[SuggestionSpan.SUGGESTIONS_MAX_SIZE];
-                for (int i = 0; i < mSuggestionInfosInContextMenu.length; i++) {
-                    mSuggestionInfosInContextMenu[i] = new SuggestionInfo();
-                }
+            final SuggestionInfo[] suggestionInfoArray =
+                    new SuggestionInfo[SuggestionSpan.SUGGESTIONS_MAX_SIZE];
+            for (int i = 0; i < suggestionInfoArray.length; i++) {
+                suggestionInfoArray[i] = new SuggestionInfo();
             }
             final SubMenu subMenu = menu.addSubMenu(Menu.NONE, Menu.NONE, MENU_ITEM_ORDER_REPLACE,
                     com.android.internal.R.string.replace);
-            mSuggestionHelper.getSuggestionInfo(mSuggestionInfosInContextMenu);
-            int i = 0;
-            for (final SuggestionInfo info : mSuggestionInfosInContextMenu) {
-                info.mSuggestionEnd = info.mText.length();
-                subMenu.add(Menu.NONE, Menu.NONE, i++, info.mText)
-                        .setOnMenuItemClickListener(mOnContextMenuReplaceItemClickListener);
+            final int numItems = mSuggestionHelper.getSuggestionInfo(suggestionInfoArray, null);
+            for (int i = 0; i < numItems; i++) {
+                final SuggestionInfo info = suggestionInfoArray[i];
+                subMenu.add(Menu.NONE, Menu.NONE, i, info.mText)
+                        .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+                            @Override
+                            public boolean onMenuItemClick(MenuItem item) {
+                                replaceWithSuggestion(info);
+                                return true;
+                            }
+                        });
             }
         }
 
@@ -2513,32 +2534,44 @@
         mPreserveSelection = true;
     }
 
-    private void replaceWithSuggestion(final SuggestionInfo suggestionInfo) {
+    @Nullable
+    private SuggestionSpan findEquivalentSuggestionSpan(
+            @NonNull SuggestionSpanInfo suggestionSpanInfo) {
         final Editable editable = (Editable) mTextView.getText();
-        if (editable.getSpanStart(suggestionInfo.mSuggestionSpan) < 0) {
-            // Suggestion span coundn't be found. Try to find a suggestion span that has the same
-            // contents.
-            final SuggestionSpan[] suggestionSpans = editable.getSpans(
-                    suggestionInfo.mSuggestionSpanStart, suggestionInfo.mSuggestionSpanEnd,
-                    SuggestionSpan.class);
-            for (final SuggestionSpan suggestionSpan : suggestionSpans) {
-                final int spanStart = editable.getSpanStart(suggestionSpan);
-                if (spanStart != suggestionInfo.mSuggestionSpanStart) {
-                    continue;
-                }
-                int spanEnd = editable.getSpanEnd(suggestionSpan);
-                if (spanEnd != suggestionInfo.mSuggestionSpanEnd) {
-                    continue;
-                }
-                if (suggestionSpan.equals(suggestionInfo.mSuggestionSpan)) {
-                    // Found.
-                    suggestionInfo.mSuggestionSpan = suggestionSpan;
-                    break;
-                }
+        if (editable.getSpanStart(suggestionSpanInfo.mSuggestionSpan) >= 0) {
+            // Exactly same span is found.
+            return suggestionSpanInfo.mSuggestionSpan;
+        }
+        // Suggestion span couldn't be found. Try to find a suggestion span that has the same
+        // contents.
+        final SuggestionSpan[] suggestionSpans = editable.getSpans(suggestionSpanInfo.mSpanStart,
+                suggestionSpanInfo.mSpanEnd, SuggestionSpan.class);
+        for (final SuggestionSpan suggestionSpan : suggestionSpans) {
+            final int start = editable.getSpanStart(suggestionSpan);
+            if (start != suggestionSpanInfo.mSpanStart) {
+                continue;
+            }
+            final int end = editable.getSpanEnd(suggestionSpan);
+            if (end != suggestionSpanInfo.mSpanEnd) {
+                continue;
+            }
+            if (suggestionSpan.equals(suggestionSpanInfo.mSuggestionSpan)) {
+                return suggestionSpan;
             }
         }
-        final int spanStart = editable.getSpanStart(suggestionInfo.mSuggestionSpan);
-        final int spanEnd = editable.getSpanEnd(suggestionInfo.mSuggestionSpan);
+        return null;
+    }
+
+    private void replaceWithSuggestion(@NonNull final SuggestionInfo suggestionInfo) {
+        final SuggestionSpan targetSuggestionSpan = findEquivalentSuggestionSpan(
+                suggestionInfo.mSuggestionSpanInfo);
+        if (targetSuggestionSpan == null) {
+            // Span has been removed
+            return;
+        }
+        final Editable editable = (Editable) mTextView.getText();
+        final int spanStart = editable.getSpanStart(targetSuggestionSpan);
+        final int spanEnd = editable.getSpanEnd(targetSuggestionSpan);
         if (spanStart < 0 || spanEnd <= spanStart) {
             // Span has been removed
             return;
@@ -2568,7 +2601,7 @@
         }
 
         // Notify source IME of the suggestion pick. Do this before swapping texts.
-        suggestionInfo.mSuggestionSpan.notifySelection(
+        targetSuggestionSpan.notifySelection(
                 mTextView.getContext(), originalText, suggestionInfo.mSuggestionIndex);
 
         // Swap text content between actual text and Suggestion span
@@ -2578,7 +2611,7 @@
                 suggestionStart, suggestionEnd).toString();
         mTextView.replaceText_internal(spanStart, spanEnd, suggestion);
 
-        String[] suggestions = suggestionInfo.mSuggestionSpan.getSuggestions();
+        String[] suggestions = targetSuggestionSpan.getSuggestions();
         suggestions[suggestionInfo.mSuggestionIndex] = originalText;
 
         // Restore previous SuggestionSpans
@@ -2608,27 +2641,6 @@
         }
     };
 
-    private final MenuItem.OnMenuItemClickListener mOnContextMenuReplaceItemClickListener =
-            new MenuItem.OnMenuItemClickListener() {
-        @Override
-        public boolean onMenuItemClick(MenuItem item) {
-            int index = item.getOrder();
-            if (index < 0 || index >= mSuggestionInfosInContextMenu.length) {
-                clear();
-                return false;
-            }
-            replaceWithSuggestion(mSuggestionInfosInContextMenu[index]);
-            clear();
-            return true;
-        }
-
-        private void clear() {
-            for (final SuggestionInfo info : mSuggestionInfosInContextMenu) {
-                info.clear();
-            }
-        }
-    };
-
     /**
      * Controls the {@link EasyEditSpan} monitoring when it is added, and when the related
      * pop-up should be displayed.
@@ -3047,19 +3059,12 @@
         }
     }
 
-    private static class SuggestionInfo {
+    private static final class SuggestionInfo {
         // Range of actual suggestion within mText
         int mSuggestionStart, mSuggestionEnd;
 
         // The SuggestionSpan that this TextView represents
-        @Nullable
-        SuggestionSpan mSuggestionSpan;
-
-        // The SuggestionSpan start position
-        int mSuggestionSpanStart;
-
-        // The SuggestionSpan end position
-        int mSuggestionSpanEnd;
+        final SuggestionSpanInfo mSuggestionSpanInfo = new SuggestionSpanInfo();
 
         // The index of this suggestion inside suggestionSpan
         int mSuggestionIndex;
@@ -3067,9 +3072,32 @@
         final SpannableStringBuilder mText = new SpannableStringBuilder();
 
         void clear() {
-            mSuggestionSpan = null;
+            mSuggestionSpanInfo.clear();
             mText.clear();
         }
+
+        // Utility method to set attributes about a SuggestionSpan.
+        void setSpanInfo(SuggestionSpan span, int spanStart, int spanEnd) {
+            mSuggestionSpanInfo.mSuggestionSpan = span;
+            mSuggestionSpanInfo.mSpanStart = spanStart;
+            mSuggestionSpanInfo.mSpanEnd = spanEnd;
+        }
+    }
+
+    private static final class SuggestionSpanInfo {
+        // The SuggestionSpan;
+        @Nullable
+        SuggestionSpan mSuggestionSpan;
+
+        // The SuggestionSpan start position
+        int mSpanStart;
+
+        // The SuggestionSpan end position
+        int mSpanEnd;
+
+        void clear() {
+            mSuggestionSpan = null;
+        }
     }
 
     private class SuggestionHelper {
@@ -3127,48 +3155,51 @@
          * position.
          *
          * @param suggestionInfos SuggestionInfo array the results will be set.
+         * @param misspelledSpanInfo a struct the misspelled SuggestionSpan info will be set.
          * @return the number of suggestions actually fetched.
          */
-        public int getSuggestionInfo(SuggestionInfo[] suggestionInfos) {
+        public int getSuggestionInfo(SuggestionInfo[] suggestionInfos,
+                @Nullable SuggestionSpanInfo misspelledSpanInfo) {
             final Spannable spannable = (Spannable) mTextView.getText();
             final SuggestionSpan[] suggestionSpans = getSortedSuggestionSpans();
             final int nbSpans = suggestionSpans.length;
             if (nbSpans == 0) return 0;
 
             int numberOfSuggestions = 0;
-            for (int spanIndex = 0; spanIndex < nbSpans; spanIndex++) {
-                final SuggestionSpan suggestionSpan = suggestionSpans[spanIndex];
+            for (final SuggestionSpan suggestionSpan : suggestionSpans) {
                 final int spanStart = spannable.getSpanStart(suggestionSpan);
                 final int spanEnd = spannable.getSpanEnd(suggestionSpan);
 
+                if (misspelledSpanInfo != null
+                        && (suggestionSpan.getFlags() & SuggestionSpan.FLAG_MISSPELLED) != 0) {
+                    misspelledSpanInfo.mSuggestionSpan = suggestionSpan;
+                    misspelledSpanInfo.mSpanStart = spanStart;
+                    misspelledSpanInfo.mSpanEnd = spanEnd;
+                }
+
                 final String[] suggestions = suggestionSpan.getSuggestions();
                 final int nbSuggestions = suggestions.length;
+                suggestionLoop:
                 for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) {
                     final String suggestion = suggestions[suggestionIndex];
-                    boolean suggestionIsDuplicate = false;
                     for (int i = 0; i < numberOfSuggestions; i++) {
-                        if (suggestionInfos[i].mText.toString().equals(suggestion)) {
-                            final SuggestionSpan otherSuggestionSpan =
-                                    suggestionInfos[i].mSuggestionSpan;
-                            final int otherSpanStart = spannable.getSpanStart(otherSuggestionSpan);
-                            final int otherSpanEnd = spannable.getSpanEnd(otherSuggestionSpan);
+                        final SuggestionInfo otherSuggestionInfo = suggestionInfos[i];
+                        if (otherSuggestionInfo.mText.toString().equals(suggestion)) {
+                            final int otherSpanStart =
+                                    otherSuggestionInfo.mSuggestionSpanInfo.mSpanStart;
+                            final int otherSpanEnd =
+                                    otherSuggestionInfo.mSuggestionSpanInfo.mSpanEnd;
                             if (spanStart == otherSpanStart && spanEnd == otherSpanEnd) {
-                                suggestionIsDuplicate = true;
-                                break;
+                                continue suggestionLoop;
                             }
                         }
                     }
 
-                    if (suggestionIsDuplicate) {
-                        continue;
-                    }
                     SuggestionInfo suggestionInfo = suggestionInfos[numberOfSuggestions];
-                    suggestionInfo.mSuggestionSpan = suggestionSpan;
+                    suggestionInfo.setSpanInfo(suggestionSpan, spanStart, spanEnd);
                     suggestionInfo.mSuggestionIndex = suggestionIndex;
                     suggestionInfo.mSuggestionStart = 0;
                     suggestionInfo.mSuggestionEnd = suggestion.length();
-                    suggestionInfo.mSuggestionSpanStart = spanStart;
-                    suggestionInfo.mSuggestionSpanEnd = spanEnd;
                     suggestionInfo.mText.replace(0, suggestionInfo.mText.length(), suggestion);
                     numberOfSuggestions++;
                     if (numberOfSuggestions >= suggestionInfos.length) {
@@ -3198,7 +3229,7 @@
         private TextView mAddToDictionaryButton;
         private TextView mDeleteButton;
         private ListView mSuggestionListView;
-        private SuggestionSpan mMisspelledSpan;
+        private final SuggestionSpanInfo mMisspelledSpanInfo = new SuggestionSpanInfo();
         private int mContainerMarginWidth;
         private int mContainerMarginTop;
 
@@ -3270,9 +3301,18 @@
                     com.android.internal.R.id.addToDictionaryButton);
             mAddToDictionaryButton.setOnClickListener(new View.OnClickListener() {
                 public void onClick(View v) {
+                    final SuggestionSpan misspelledSpan =
+                            findEquivalentSuggestionSpan(mMisspelledSpanInfo);
+                    if (misspelledSpan == null) {
+                        // Span has been removed.
+                        return;
+                    }
                     final Editable editable = (Editable) mTextView.getText();
-                    final int spanStart = editable.getSpanStart(mMisspelledSpan);
-                    final int spanEnd = editable.getSpanEnd(mMisspelledSpan);
+                    final int spanStart = editable.getSpanStart(misspelledSpan);
+                    final int spanEnd = editable.getSpanEnd(misspelledSpan);
+                    if (spanStart < 0 || spanEnd <= spanStart) {
+                        return;
+                    }
                     final String originalText = TextUtils.substring(editable, spanStart, spanEnd);
 
                     final Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT);
@@ -3283,7 +3323,7 @@
                     mTextView.getContext().startActivity(intent);
                     // There is no way to know if the word was indeed added. Re-check.
                     // TODO The ExtractEditText should remove the span in the original text instead
-                    editable.removeSpan(mMisspelledSpan);
+                    editable.removeSpan(mMisspelledSpanInfo.mSuggestionSpan);
                     Selection.setSelection(editable, spanEnd);
                     updateSpellCheckSpans(spanStart, spanEnd, false);
                     hideWithCleanUp();
@@ -3440,30 +3480,29 @@
             for (final SuggestionInfo info : mSuggestionInfos) {
                 info.clear();
             }
-            mMisspelledSpan = null;
+            mMisspelledSpanInfo.clear();
             hide();
         }
 
         private boolean updateSuggestions() {
             Spannable spannable = (Spannable) mTextView.getText();
             mNumberOfSuggestions =
-                    mSuggestionHelper.getSuggestionInfo(mSuggestionInfos);
-            if (mNumberOfSuggestions == 0) {
+                    mSuggestionHelper.getSuggestionInfo(mSuggestionInfos, mMisspelledSpanInfo);
+            if (mNumberOfSuggestions == 0 && mMisspelledSpanInfo.mSuggestionSpan == null) {
                 return false;
             }
 
             int spanUnionStart = mTextView.getText().length();
             int spanUnionEnd = 0;
 
-            mMisspelledSpan = null;
             for (int i = 0; i < mNumberOfSuggestions; i++) {
-                final SuggestionInfo suggestionInfo = mSuggestionInfos[i];
-                final SuggestionSpan suggestionSpan = suggestionInfo.mSuggestionSpan;
-                if ((suggestionSpan.getFlags() & SuggestionSpan.FLAG_MISSPELLED) != 0) {
-                    mMisspelledSpan = suggestionSpan;
-                }
-                spanUnionStart = Math.min(spanUnionStart, suggestionInfo.mSuggestionSpanStart);
-                spanUnionEnd = Math.max(spanUnionEnd, suggestionInfo.mSuggestionSpanEnd);
+                final SuggestionSpanInfo spanInfo = mSuggestionInfos[i].mSuggestionSpanInfo;
+                spanUnionStart = Math.min(spanUnionStart, spanInfo.mSpanStart);
+                spanUnionEnd = Math.max(spanUnionEnd, spanInfo.mSpanEnd);
+            }
+            if (mMisspelledSpanInfo.mSuggestionSpan != null) {
+                spanUnionStart = Math.min(spanUnionStart, mMisspelledSpanInfo.mSpanStart);
+                spanUnionEnd = Math.max(spanUnionEnd, mMisspelledSpanInfo.mSpanEnd);
             }
 
             for (int i = 0; i < mNumberOfSuggestions; i++) {
@@ -3472,17 +3511,23 @@
 
             // Make "Add to dictionary" item visible if there is a span with the misspelled flag
             int addToDictionaryButtonVisibility = View.GONE;
-            if (mMisspelledSpan != null) {
-                final int misspelledStart = spannable.getSpanStart(mMisspelledSpan);
-                final int misspelledEnd = spannable.getSpanEnd(mMisspelledSpan);
-                if (misspelledStart >= 0 && misspelledEnd > misspelledStart) {
+            if (mMisspelledSpanInfo.mSuggestionSpan != null) {
+                if (mMisspelledSpanInfo.mSpanStart >= 0
+                        && mMisspelledSpanInfo.mSpanEnd > mMisspelledSpanInfo.mSpanStart) {
                     addToDictionaryButtonVisibility = View.VISIBLE;
                 }
             }
             mAddToDictionaryButton.setVisibility(addToDictionaryButtonVisibility);
 
             if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan();
-            final int underlineColor = mSuggestionInfos[0].mSuggestionSpan.getUnderlineColor();
+            final int underlineColor;
+            if (mNumberOfSuggestions != 0) {
+                underlineColor =
+                        mSuggestionInfos[0].mSuggestionSpanInfo.mSuggestionSpan.getUnderlineColor();
+            } else {
+                underlineColor = mMisspelledSpanInfo.mSuggestionSpan.getUnderlineColor();
+            }
+
             if (underlineColor == 0) {
                 // Fallback on the default highlight color when the first span does not provide one
                 mSuggestionRangeSpan.setBackgroundColor(mTextView.mHighlightColor);
@@ -3502,8 +3547,8 @@
         private void highlightTextDifferences(SuggestionInfo suggestionInfo, int unionStart,
                 int unionEnd) {
             final Spannable text = (Spannable) mTextView.getText();
-            final int spanStart = suggestionInfo.mSuggestionSpanStart;
-            final int spanEnd = suggestionInfo.mSuggestionSpanEnd;
+            final int spanStart = suggestionInfo.mSuggestionSpanInfo.mSpanStart;
+            final int spanEnd = suggestionInfo.mSuggestionSpanInfo.mSpanEnd;
 
             // Adjust the start/end of the suggestion span
             suggestionInfo.mSuggestionStart = spanStart - unionStart;
@@ -3679,6 +3724,8 @@
 
         @Override
         public void onDestroyActionMode(ActionMode mode) {
+            // Clear mTextActionMode not to recursively destroy action mode by clearing selection.
+            mTextActionMode = null;
             Callback customCallback = getCustomCallback();
             if (customCallback != null) {
                 customCallback.onDestroyActionMode(mode);
@@ -3697,8 +3744,6 @@
             if (mSelectionModifierCursorController != null) {
                 mSelectionModifierCursorController.hide();
             }
-
-            mTextActionMode = null;
         }
 
         @Override
@@ -5101,27 +5146,12 @@
                     // No longer dragging to select text, let the parent intercept events.
                     mTextView.getParent().requestDisallowInterceptTouchEvent(false);
 
-                    int startOffset = mTextView.getSelectionStart();
-                    int endOffset = mTextView.getSelectionEnd();
-
-                    // Since we don't let drag handles pass once they're visible, we need to
-                    // make sure the start / end locations are correct because the user *can*
-                    // switch directions during the initial drag.
-                    if (endOffset < startOffset) {
-                        int tmp = endOffset;
-                        endOffset = startOffset;
-                        startOffset = tmp;
-
-                        // Also update the selection with the right offsets in this case.
-                        Selection.setSelection((Spannable) mTextView.getText(),
-                                startOffset, endOffset);
-                    }
-                    if (startOffset != endOffset) {
-                        startSelectionActionMode();
-                    }
-
                     // No longer the first dragging motion, reset.
                     resetDragAcceleratorState();
+
+                    if (mTextView.hasSelection()) {
+                        startSelectionActionMode();
+                    }
                     break;
             }
         }
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 1321221..6d7313d 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1644,7 +1644,7 @@
         boolean handled = false;
         int action = event.getAction();
         if (KeyEvent.isConfirmKey(keyCode)
-                && event.hasNoModifiers() && action == KeyEvent.ACTION_UP) {
+                && event.hasNoModifiers() && action != KeyEvent.ACTION_UP) {
             handled = resurrectSelectionIfNeeded();
             if (!handled && event.getRepeatCount() == 0 && getChildCount() > 0) {
                 keyPressed();
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index f601f7d..04d344f 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -212,7 +212,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable dr) {
+    protected boolean verifyDrawable(@NonNull Drawable dr) {
         return mDrawable == dr || super.verifyDrawable(dr);
     }
 
@@ -223,7 +223,7 @@
     }
 
     @Override
-    public void invalidateDrawable(Drawable dr) {
+    public void invalidateDrawable(@NonNull Drawable dr) {
         if (dr == mDrawable) {
             if (dr != null) {
                 // update cached drawable dimensions if they've changed
@@ -913,6 +913,7 @@
         if (mDrawable != null) {
             mDrawable.setCallback(null);
             unscheduleDrawable(mDrawable);
+            mDrawable.setVisible(false, false);
         }
 
         mDrawable = d;
@@ -923,7 +924,8 @@
             if (d.isStateful()) {
                 d.setState(getDrawableState());
             }
-            d.setVisible(getVisibility() == VISIBLE, true);
+            d.setVisible(isAttachedToWindow() && getWindowVisibility() == VISIBLE && isShown(),
+                    true);
             d.setLevel(mLevel);
             mDrawableWidth = d.getIntrinsicWidth();
             mDrawableHeight = d.getIntrinsicHeight();
@@ -1498,28 +1500,11 @@
         }
     }
 
-    @RemotableViewMethod
     @Override
-    public void setVisibility(int visibility) {
-        super.setVisibility(visibility);
+    public void onVisibilityAggregated(boolean isVisible) {
+        super.onVisibilityAggregated(isVisible);
         if (mDrawable != null) {
-            mDrawable.setVisible(visibility == VISIBLE, false);
-        }
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        if (mDrawable != null) {
-            mDrawable.setVisible(getVisibility() == VISIBLE, false);
-        }
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-        if (mDrawable != null) {
-            mDrawable.setVisible(false, false);
+            mDrawable.setVisible(isVisible, false);
         }
     }
 
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 72a50ec1..e9fa26c 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -246,6 +246,8 @@
 
     boolean mMirrorForRtl = false;
 
+    private boolean mAggregatedIsVisible;
+
     private final ArrayList<RefreshData> mRefreshData = new ArrayList<RefreshData>();
 
     private AccessibilityEventSender mAccessibilityEventSender;
@@ -615,14 +617,13 @@
     private void swapCurrentDrawable(Drawable newDrawable) {
         final Drawable oldDrawable = mCurrentDrawable;
         mCurrentDrawable = newDrawable;
+
         if (oldDrawable != mCurrentDrawable) {
             if (oldDrawable != null) {
                 oldDrawable.setVisible(false, false);
             }
             if (mCurrentDrawable != null) {
-                mCurrentDrawable.setVisible(
-                        getVisibility() == VISIBLE && getWindowVisibility() == VISIBLE,
-                        false);
+                mCurrentDrawable.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
             }
         }
     }
@@ -1229,7 +1230,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return who == mProgressDrawable || who == mIndeterminateDrawable
                 || super.verifyDrawable(who);
     }
@@ -1645,54 +1646,29 @@
     }
 
     @Override
-    @RemotableViewMethod
-    public void setVisibility(int v) {
-        if (getVisibility() != v) {
-            super.setVisibility(v);
+    public void onVisibilityAggregated(boolean isVisible) {
+        super.onVisibilityAggregated(isVisible);
+
+        if (isVisible != mAggregatedIsVisible) {
+            mAggregatedIsVisible = isVisible;
 
             if (mIndeterminate) {
                 // let's be nice with the UI thread
-                if (v == GONE || v == INVISIBLE) {
-                    stopAnimation();
-                } else {
+                if (isVisible) {
                     startAnimation();
+                } else {
+                    stopAnimation();
                 }
             }
-        }
-    }
 
-    @Override
-    protected void onVisibilityChanged(View changedView, int visibility) {
-        super.onVisibilityChanged(changedView, visibility);
-
-        updateVisibility();
-    }
-
-    @Override
-    protected void onWindowVisibilityChanged(@Visibility int visibility) {
-        super.onWindowVisibilityChanged(visibility);
-
-        updateVisibility();
-    }
-
-    private void updateVisibility() {
-        final boolean isVisible = getVisibility() == VISIBLE && getWindowVisibility() == VISIBLE;
-        if (mIndeterminate) {
-            // let's be nice with the UI thread
-            if (isVisible) {
-                startAnimation();
-            } else {
-                stopAnimation();
+            if (mCurrentDrawable != null) {
+                mCurrentDrawable.setVisible(isVisible, false);
             }
         }
-
-        if (mCurrentDrawable != null) {
-            mCurrentDrawable.setVisible(isVisible, false);
-        }
     }
 
     @Override
-    public void invalidateDrawable(Drawable dr) {
+    public void invalidateDrawable(@NonNull Drawable dr) {
         if (!mInDrawing) {
             if (verifyDrawable(dr)) {
                 final Rect dirty = dr.getBounds();
diff --git a/core/java/android/widget/ScrollBarDrawable.java b/core/java/android/widget/ScrollBarDrawable.java
index 8880217..11eab2a 100644
--- a/core/java/android/widget/ScrollBarDrawable.java
+++ b/core/java/android/widget/ScrollBarDrawable.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.widget.ScrollBarUtils;
 
+import android.annotation.NonNull;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.PixelFormat;
@@ -362,17 +363,17 @@
     }
 
     @Override
-    public void invalidateDrawable(Drawable who) {
+    public void invalidateDrawable(@NonNull Drawable who) {
         invalidateSelf();
     }
 
     @Override
-    public void scheduleDrawable(Drawable who, Runnable what, long when) {
+    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
         scheduleSelf(what, when);
     }
 
     @Override
-    public void unscheduleDrawable(Drawable who, Runnable what) {
+    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
         unscheduleSelf(what);
     }
 
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index 6edce91..43cf5a1 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -33,6 +33,7 @@
 import android.text.format.DateFormat;
 import android.util.AttributeSet;
 import android.util.IntArray;
+import android.util.Log;
 import android.util.MathUtils;
 import android.util.StateSet;
 import android.view.KeyEvent;
@@ -47,6 +48,7 @@
 import com.android.internal.widget.ExploreByTouchHelper;
 
 import java.text.NumberFormat;
+import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Locale;
 
@@ -55,17 +57,22 @@
  * within the specified month.
  */
 class SimpleMonthView extends View {
+    private static final String LOG_TAG = "SimpleMonthView";
+
     private static final int DAYS_IN_WEEK = 7;
     private static final int MAX_WEEKS_IN_MONTH = 6;
 
     private static final int DEFAULT_SELECTED_DAY = -1;
     private static final int DEFAULT_WEEK_START = Calendar.SUNDAY;
 
-    private static final String DEFAULT_TITLE_FORMAT = "MMMMy";
+    private static final String MONTH_YEAR_FORMAT = "MMMMy";
     private static final String DAY_OF_WEEK_FORMAT = "EEEEE";
 
     private static final int SELECTED_HIGHLIGHT_ALPHA = 0xB0;
 
+    /** Temporary until we figure out why the date gets messed up. */
+    private static final boolean DEBUG_WRONG_DATE = true;
+
     private final TextPaint mMonthPaint = new TextPaint();
     private final TextPaint mDayOfWeekPaint = new TextPaint();
     private final TextPaint mDayPaint = new TextPaint();
@@ -73,13 +80,13 @@
     private final Paint mDayHighlightPaint = new Paint();
     private final Paint mDayHighlightSelectorPaint = new Paint();
 
-    private final Calendar mCalendar = Calendar.getInstance();
-    private final Calendar mDayOfWeekLabelCalendar = Calendar.getInstance();
+    private final String[] mDayOfWeekLabels = new String[7];
+
+    private final Calendar mCalendar;
+    private final Locale mLocale;
 
     private final MonthViewTouchHelper mTouchHelper;
 
-    private final SimpleDateFormat mTitleFormatter;
-    private final SimpleDateFormat mDayOfWeekFormatter;
     private final NumberFormat mDayFormatter;
 
     // Desired dimensions.
@@ -89,7 +96,7 @@
     private final int mDesiredCellWidth;
     private final int mDesiredDaySelectorRadius;
 
-    private CharSequence mTitle;
+    private String mMonthYearLabel;
 
     private int mMonth;
     private int mYear;
@@ -168,15 +175,44 @@
         setAccessibilityDelegate(mTouchHelper);
         setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
 
-        final Locale locale = res.getConfiguration().locale;
-        final String titleFormat = DateFormat.getBestDateTimePattern(locale, DEFAULT_TITLE_FORMAT);
-        mTitleFormatter = new SimpleDateFormat(titleFormat, locale);
-        mDayOfWeekFormatter = new SimpleDateFormat(DAY_OF_WEEK_FORMAT, locale);
-        mDayFormatter = NumberFormat.getIntegerInstance(locale);
+        mLocale = res.getConfiguration().locale;
+        mCalendar = Calendar.getInstance(mLocale);
+
+        mDayFormatter = NumberFormat.getIntegerInstance(mLocale);
+
+        updateMonthYearLabel();
+        updateDayOfWeekLabels();
 
         initPaints(res);
     }
 
+    private void updateMonthYearLabel() {
+        final String format = DateFormat.getBestDateTimePattern(mLocale, MONTH_YEAR_FORMAT);
+        final SimpleDateFormat formatter = new SimpleDateFormat(format, mLocale);
+        mMonthYearLabel = formatter.format(mCalendar.getTime());
+    }
+
+    private void updateDayOfWeekLabels() {
+        if (DEBUG_WRONG_DATE) {
+            Log.d(LOG_TAG, "enter updateDayOfWeekLabels()", new Exception());
+            Log.d(LOG_TAG, "mLocale => " + mLocale);
+            Log.d(LOG_TAG, "mWeekStart => " + mWeekStart);
+        }
+
+        final Calendar calendar = Calendar.getInstance(mLocale);
+        calendar.setFirstDayOfWeek(mWeekStart);
+
+        final SimpleDateFormat formatter = new SimpleDateFormat(DAY_OF_WEEK_FORMAT, mLocale);
+        for (int i = 0; i < 7; i++) {
+            calendar.set(Calendar.DAY_OF_WEEK, i);
+            mDayOfWeekLabels[i] = formatter.format(calendar.getTime());
+        }
+
+        if (DEBUG_WRONG_DATE) {
+            Log.d(LOG_TAG, "mDayOfWeekLabels <= " + Arrays.toString(mDayOfWeekLabels));
+        }
+    }
+
     /**
      * Applies the specified text appearance resource to a paint, returning the
      * text color if one is set in the text appearance.
@@ -236,13 +272,6 @@
         invalidate();
     }
 
-    public CharSequence getTitle() {
-        if (mTitle == null) {
-            mTitle = mTitleFormatter.format(mCalendar.getTime());
-        }
-        return mTitle;
-    }
-
     /**
      * Sets up the text and style properties for painting.
      */
@@ -607,7 +636,11 @@
         final float lineHeight = mMonthPaint.ascent() + mMonthPaint.descent();
         final float y = (mMonthHeight - lineHeight) / 2f;
 
-        canvas.drawText(getTitle().toString(), x, y, mMonthPaint);
+        canvas.drawText(mMonthYearLabel, x, y, mMonthPaint);
+    }
+
+    public String getMonthYearLabel() {
+        return mMonthYearLabel;
     }
 
     private void drawDaysOfWeek(Canvas canvas) {
@@ -630,16 +663,11 @@
             }
 
             final int dayOfWeek = (col + mWeekStart) % DAYS_IN_WEEK;
-            final String label = getDayOfWeekLabel(dayOfWeek);
+            final String label = mDayOfWeekLabels[dayOfWeek];
             canvas.drawText(label, colCenterRtl, rowCenter - halfLineHeight, p);
         }
     }
 
-    private String getDayOfWeekLabel(int dayOfWeek) {
-        mDayOfWeekLabelCalendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
-        return mDayOfWeekFormatter.format(mDayOfWeekLabelCalendar.getTime());
-    }
-
     /**
      * Draws the month days.
      */
@@ -746,12 +774,22 @@
      *                  {@link Calendar#SUNDAY} through {@link Calendar#SATURDAY}
      */
     public void setFirstDayOfWeek(int weekStart) {
+        if (DEBUG_WRONG_DATE) {
+            Log.d(LOG_TAG, "enter setFirstDayOfWeek(" + weekStart + ")", new Exception());
+        }
+
         if (isValidDayOfWeek(weekStart)) {
             mWeekStart = weekStart;
         } else {
             mWeekStart = mCalendar.getFirstDayOfWeek();
         }
 
+        if (DEBUG_WRONG_DATE) {
+            Log.d(LOG_TAG, "mWeekStart <=" + mWeekStart);
+        }
+
+        updateDayOfWeekLabels();
+
         // Invalidate cached accessibility information.
         mTouchHelper.invalidateRoot();
         invalidate();
@@ -807,11 +845,10 @@
         mEnabledDayStart = MathUtils.constrain(enabledDayStart, 1, mDaysInMonth);
         mEnabledDayEnd = MathUtils.constrain(enabledDayEnd, mEnabledDayStart, mDaysInMonth);
 
-        // Invalidate the old title.
-        mTitle = null;
-
         // Invalidate cached accessibility information.
         mTouchHelper.invalidateRoot();
+
+        updateMonthYearLabel();
     }
 
     private static int getDaysInMonth(int month, int year) {
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 434516d..c4a1771 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -18,6 +18,7 @@
 
 import android.animation.ObjectAnimator;
 import android.annotation.DrawableRes;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StyleRes;
 import android.content.Context;
@@ -1371,7 +1372,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return super.verifyDrawable(who) || who == mThumbDrawable || who == mTrackDrawable;
     }
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index ac3eaf7..8a1a8c5 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3071,7 +3071,14 @@
      * @attr ref android.R.styleable#TextView_elegantTextHeight
      */
     public void setElegantTextHeight(boolean elegant) {
-        mTextPaint.setElegantTextHeight(elegant);
+        if (elegant != mTextPaint.isElegantTextHeight()) {
+            mTextPaint.setElegantTextHeight(elegant);
+            if (mLayout != null) {
+                nullLayouts();
+                requestLayout();
+                invalidate();
+            }
+        }
     }
 
     /**
@@ -5463,7 +5470,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         final boolean verified = super.verifyDrawable(who);
         if (!verified && mDrawables != null) {
             for (Drawable dr : mDrawables.mShowing) {
@@ -5488,7 +5495,7 @@
     }
 
     @Override
-    public void invalidateDrawable(Drawable drawable) {
+    public void invalidateDrawable(@NonNull Drawable drawable) {
         boolean handled = false;
 
         if (verifyDrawable(drawable)) {
@@ -6545,7 +6552,7 @@
                 if (TextUtils.equals(content.subSequence(start, end), text.text)) {
                     if (text.text instanceof Spanned) {
                         // OK to copy spans only.
-                        TextUtils.copySpansFrom((Spanned) text.text, start, end,
+                        TextUtils.copySpansFrom((Spanned) text.text, 0, end - start,
                                 Object.class, content, start);
                     }
                 } else {
@@ -8916,8 +8923,7 @@
     }
 
     void onLocaleChanged() {
-        // Will be re-created on demand in getWordIterator with the proper new locale
-        mEditor.mWordIterator = null;
+        mEditor.onLocaleChanged();
     }
 
     /**
@@ -9206,6 +9212,10 @@
                     }
                     if (start >= 0 && start <= end && end <= text.length()) {
                         Selection.setSelection((Spannable) text, start, end);
+                        // Make sure selection mode is engaged.
+                        if (mEditor != null) {
+                            mEditor.startSelectionActionMode();
+                        }
                         return true;
                     }
                 }
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index b13be97..3a31b37 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -45,6 +45,6 @@
     void setAudioRestriction(int code, int usage, int uid, int mode, in String[] exceptionPackages);
 
     void setUserRestrictions(in Bundle restrictions, IBinder token, int userHandle);
-    void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle);
+    void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle, in String[] exceptionPackages);
     void removeUser(int userHandle);
 }
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 74fe94f..8e38c5a 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -20,6 +20,7 @@
 
 import android.os.ParcelFileDescriptor;
 import android.os.WorkSource;
+import android.os.health.HealthStatsParceler;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.SignalStrength;
 
@@ -125,4 +126,7 @@
     void noteBleScanStarted(in WorkSource ws);
     void noteBleScanStopped(in WorkSource ws);
     void noteResetBleScan();
+
+    HealthStatsParceler takeUidSnapshot(int uid);
+    HealthStatsParceler[] takeUidSnapshots(in int[] uid);
 }
diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
index 29190f9..f6fbaab 100644
--- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java
+++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
@@ -42,15 +42,13 @@
 
 /**
  * A dialog shown to the user when they try to launch an app from a quiet profile
- * ({@link UserManager#isQuietModeEnabled(UserHandle)}, or when the app is suspended by the
- * profile owner or device owner.
+ * ({@link UserManager#isQuietModeEnabled(UserHandle)}.
  */
 public class UnlaunchableAppActivity extends Activity
         implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener {
     private static final String TAG = "UnlaunchableAppActivity";
 
     private static final int UNLAUNCHABLE_REASON_QUIET_MODE = 1;
-    private static final int UNLAUNCHABLE_REASON_SUSPENDED_PACKAGE = 2;
     private static final String EXTRA_UNLAUNCHABLE_REASON = "unlaunchable_reason";
 
     private int mUserId;
@@ -74,37 +72,6 @@
         if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE) {
             dialogTitle = getResources().getString(R.string.work_mode_off_title);
             dialogMessage = getResources().getString(R.string.work_mode_off_message);
-        } else if (mReason == UNLAUNCHABLE_REASON_SUSPENDED_PACKAGE) {
-            DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(
-                    Context.DEVICE_POLICY_SERVICE);
-            String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
-            String packageLabel = packageName;
-            try {
-                Context userContext = createPackageContextAsUser(packageName, 0,
-                        UserHandle.of(mUserId));
-                ApplicationInfo appInfo = userContext.getApplicationInfo();
-                if (appInfo != null) {
-                    packageLabel = userContext.getPackageManager().getApplicationLabel(appInfo)
-                            .toString();
-                }
-            } catch (NameNotFoundException e) {
-            }
-            dialogTitle = String.format(getResources().getString(R.string.suspended_package_title),
-                    packageLabel);
-            ComponentName profileOwner = dpm.getProfileOwnerAsUser(mUserId);
-            String profileOwnerName = null;
-            if (profileOwner != null) {
-                dialogMessage = dpm.getShortSupportMessageForUser(profileOwner, mUserId);
-                profileOwnerName = dpm.getProfileOwnerNameAsUser(mUserId);
-            }
-            // Fall back to standard message if profile owner hasn't set something specific.
-            if (TextUtils.isEmpty(dialogMessage)) {
-                if (TextUtils.isEmpty(profileOwnerName)) {
-                    profileOwnerName = getResources().getString(R.string.unknownName);
-                }
-                dialogMessage = getResources().getString(R.string.suspended_package_message,
-                        profileOwnerName);
-            }
         } else {
             Log.wtf(TAG, "Invalid unlaunchable type: " + mReason);
             finish();
@@ -154,12 +121,4 @@
         intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
         return intent;
     }
-
-    public static Intent createPackageSuspendedDialogIntent(String packageName, int userId) {
-        Intent intent = createBaseIntent();
-        intent.putExtra(EXTRA_UNLAUNCHABLE_REASON, UNLAUNCHABLE_REASON_SUSPENDED_PACKAGE);
-        intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
-        intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
-        return intent;
-    }
 }
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index f04bcf2..9461ce6 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -505,7 +505,6 @@
         final int numSubtypes = subtypes.size();
 
         // Handle overridesImplicitlyEnabledSubtype mechanism.
-        final String systemLanguage = systemLocales.get(0).getLanguage();
         final HashMap<String, InputMethodSubtype> applicableModeAndSubtypesMap = new HashMap<>();
         for (int i = 0; i < numSubtypes; ++i) {
             // scan overriding implicitly enabled subtypes.
@@ -521,25 +520,20 @@
             return new ArrayList<>(applicableModeAndSubtypesMap.values());
         }
 
+        final HashMap<String, ArrayList<InputMethodSubtype>> nonKeyboardSubtypesMap =
+                new HashMap<>();
         final ArrayList<InputMethodSubtype> keyboardSubtypes = new ArrayList<>();
+
         for (int i = 0; i < numSubtypes; ++i) {
             final InputMethodSubtype subtype = subtypes.get(i);
-            if (TextUtils.equals(SUBTYPE_MODE_KEYBOARD, subtype.getMode())) {
+            final String mode = subtype.getMode();
+            if (SUBTYPE_MODE_KEYBOARD.equals(mode)) {
                 keyboardSubtypes.add(subtype);
             } else {
-                final Locale locale = subtype.getLocaleObject();
-                final String mode = subtype.getMode();
-                // TODO: Take secondary system locales into consideration.
-                if (locale != null && locale.equals(systemLanguage)) {
-                    final InputMethodSubtype applicableSubtype =
-                            applicableModeAndSubtypesMap.get(mode);
-                    // If more applicable subtypes are contained, skip.
-                    if (applicableSubtype != null) {
-                        if (systemLocale.equals(applicableSubtype.getLocaleObject())) continue;
-                        if (!systemLocale.equals(locale)) continue;
-                    }
-                    applicableModeAndSubtypesMap.put(mode, subtype);
+                if (!nonKeyboardSubtypesMap.containsKey(mode)) {
+                    nonKeyboardSubtypesMap.put(mode, new ArrayList<>());
                 }
+                nonKeyboardSubtypesMap.get(mode).add(subtype);
             }
         }
 
@@ -578,7 +572,12 @@
             }
         }
 
-        applicableSubtypes.addAll(applicableModeAndSubtypesMap.values());
+        // For each non-keyboard mode, extract subtypes with system locales.
+        for (final ArrayList<InputMethodSubtype> subtypeList : nonKeyboardSubtypesMap.values()) {
+            LocaleUtils.filterByLanguage(subtypeList, sSubtypeToLocale, systemLocales,
+                    applicableSubtypes);
+        }
+
         return applicableSubtypes;
     }
 
@@ -855,7 +854,8 @@
         private final HashMap<String, String> mCopyOnWriteDataStore = new HashMap<>();
 
         private boolean mCopyOnWrite = false;
-        private String mEnabledInputMethodsStrCache;
+        @NonNull
+        private String mEnabledInputMethodsStrCache = "";
         @UserIdInt
         private int mCurrentUserId;
         private int[] mCurrentProfileIds = new int[0];
@@ -950,7 +950,7 @@
             // TODO: mCurrentProfileIds should be updated here.
         }
 
-        private void putString(final String key, final String str) {
+        private void putString(@NonNull final String key, @Nullable final String str) {
             if (mCopyOnWrite) {
                 mCopyOnWriteDataStore.put(key, str);
             } else {
@@ -958,12 +958,15 @@
             }
         }
 
-        private String getString(final String key) {
+        @Nullable
+        private String getString(@NonNull final String key, @Nullable final String defaultValue) {
+            final String result;
             if (mCopyOnWrite && mCopyOnWriteDataStore.containsKey(key)) {
-                final String result = mCopyOnWriteDataStore.get(key);
-                return result != null ? result : "";
+                result = mCopyOnWriteDataStore.get(key);
+            } else {
+                result = Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
             }
-            return Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
+            return result != null ? result : defaultValue;
         }
 
         private void putInt(final String key, final int value) {
@@ -1125,16 +1128,24 @@
             return res;
         }
 
-        private void putEnabledInputMethodsStr(String str) {
+        private void putEnabledInputMethodsStr(@Nullable String str) {
             if (DEBUG) {
                 Slog.d(TAG, "putEnabledInputMethodStr: " + str);
             }
-            putString(Settings.Secure.ENABLED_INPUT_METHODS, str);
-            mEnabledInputMethodsStrCache = str;
+            if (TextUtils.isEmpty(str)) {
+                // OK to coalesce to null, since getEnabledInputMethodsStr() can take care of the
+                // empty data scenario.
+                putString(Settings.Secure.ENABLED_INPUT_METHODS, null);
+            } else {
+                putString(Settings.Secure.ENABLED_INPUT_METHODS, str);
+            }
+            // TODO: Update callers of putEnabledInputMethodsStr to make str @NonNull.
+            mEnabledInputMethodsStrCache = (str != null ? str : "");
         }
 
+        @NonNull
         public String getEnabledInputMethodsStr() {
-            mEnabledInputMethodsStrCache = getString(Settings.Secure.ENABLED_INPUT_METHODS);
+            mEnabledInputMethodsStrCache = getString(Settings.Secure.ENABLED_INPUT_METHODS, "");
             if (DEBUG) {
                 Slog.d(TAG, "getEnabledInputMethodsStr: " + mEnabledInputMethodsStrCache
                         + ", " + mCurrentUserId);
@@ -1188,11 +1199,17 @@
             saveSubtypeHistory(subtypeHistory, imeId, subtypeId);
         }
 
-        private void putSubtypeHistoryStr(String str) {
+        private void putSubtypeHistoryStr(@NonNull String str) {
             if (DEBUG) {
                 Slog.d(TAG, "putSubtypeHistoryStr: " + str);
             }
-            putString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, str);
+            if (TextUtils.isEmpty(str)) {
+                // OK to coalesce to null, since getSubtypeHistoryStr() can take care of the empty
+                // data scenario.
+                putString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, null);
+            } else {
+                putString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, str);
+            }
         }
 
         public Pair<String, String> getLastInputMethodAndSubtypeLocked() {
@@ -1309,8 +1326,9 @@
             return imsList;
         }
 
+        @NonNull
         private String getSubtypeHistoryStr() {
-            final String history = getString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY);
+            final String history = getString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, "");
             if (DEBUG) {
                 Slog.d(TAG, "getSubtypeHistoryStr: " + history);
             }
@@ -1333,8 +1351,9 @@
             putInt(Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, subtypeId);
         }
 
+        @Nullable
         public String getSelectedInputMethod() {
-            final String imi = getString(Settings.Secure.DEFAULT_INPUT_METHOD);
+            final String imi = getString(Settings.Secure.DEFAULT_INPUT_METHOD, null);
             if (DEBUG) {
                 Slog.d(TAG, "getSelectedInputMethodStr: " + imi);
             }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 60c9e14..8de9c09 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -1953,7 +1953,7 @@
          */
         @Override
         public LongSamplingCounter getIdleTimeCounter() {
-            return mRxTimeMillis;
+            return mIdleTimeMillis;
         }
 
         /**
@@ -5300,6 +5300,12 @@
         }
 
         @Override
+        public Timer getProcessStateTimer(int state) {
+            if (state < 0 || state >= NUM_PROCESS_STATE) return null;
+            return mProcessStateTimer[state];
+        }
+
+        @Override
         public Timer getVibratorOnTimer() {
             return mVibratorOnTimer;
         }
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index df48d6d..fbd8fb5 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -2073,11 +2073,7 @@
     public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> list) {
         final PanelFeatureState st = mWindow.getPanelState(FEATURE_OPTIONS_PANEL, false);
         if (!mWindow.isDestroyed() && st != null && mWindow.getCallback() != null) {
-            try {
-                mWindow.getCallback().onProvideKeyboardShortcuts(list, st.menu);
-            } catch (AbstractMethodError e) {
-                // We run into this if the app is using supportlib.
-            }
+            mWindow.getCallback().onProvideKeyboardShortcuts(list, st.menu);
         }
     }
 
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index 84d0fc7..9907ea9 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -279,6 +279,26 @@
     }
 
     /**
+     * Cycles through all non-dismiss targets with a stepping of {@param increment}. It moves left
+     * if {@param increment} is negative and moves right otherwise.
+     */
+    public SnapTarget cycleNonDismissTarget(SnapTarget snapTarget, int increment) {
+        int index = mTargets.indexOf(snapTarget);
+        if (index != -1) {
+            SnapTarget newTarget = mTargets.get((index + mTargets.size() + increment)
+                    % mTargets.size());
+            if (newTarget == mDismissStartTarget) {
+                return mLastSplitTarget;
+            } else if (newTarget == mDismissEndTarget) {
+                return mFirstSplitTarget;
+            } else {
+                return newTarget;
+            }
+        }
+        return snapTarget;
+    }
+
+    /**
      * Represents a snap target for the divider.
      */
     public static class SnapTarget {
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index a84a061..ee73b90 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -27,6 +27,7 @@
 import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 
@@ -477,4 +478,48 @@
         }
         return !diff;
     }
+
+    /**
+     * Removes elements that match the predicate in an efficient way that alters the order of
+     * elements in the collection. This should only be used if order is not important.
+     * @param collection The ArrayList from which to remove elements.
+     * @param predicate The predicate that each element is tested against.
+     * @return the number of elements removed.
+     */
+    public static <T> int unstableRemoveIf(@Nullable ArrayList<T> collection,
+                                           @NonNull java.util.function.Predicate<T> predicate) {
+        if (collection == null) {
+            return 0;
+        }
+
+        final int size = collection.size();
+        int leftIdx = 0;
+        int rightIdx = size - 1;
+        while (leftIdx <= rightIdx) {
+            // Find the next element to remove moving left to right.
+            while (leftIdx < size && !predicate.test(collection.get(leftIdx))) {
+                leftIdx++;
+            }
+
+            // Find the next element to keep moving right to left.
+            while (rightIdx > leftIdx && predicate.test(collection.get(rightIdx))) {
+                rightIdx--;
+            }
+
+            if (leftIdx >= rightIdx) {
+                // Done.
+                break;
+            }
+
+            Collections.swap(collection, leftIdx, rightIdx);
+            leftIdx++;
+            rightIdx--;
+        }
+
+        // leftIdx is now at the end.
+        for (int i = size - 1; i >= leftIdx; i--) {
+            collection.remove(i);
+        }
+        return size - leftIdx;
+    }
 }
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index 398bbe7..baf3188 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -147,7 +147,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return (who == mBackground && !mIsSplit) || (who == mStackedBackground && mIsStacked) ||
                 (who == mSplitBackground && mIsSplit) || super.verifyDrawable(who);
     }
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index 948a6bb..277fafd 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -17,6 +17,7 @@
 package com.android.internal.widget;
 
 import android.annotation.DrawableRes;
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -746,7 +747,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return super.verifyDrawable(who) || who == mMarginDrawable;
     }
 
diff --git a/core/java/com/android/server/backup/SystemBackupAgent.java b/core/java/com/android/server/backup/SystemBackupAgent.java
index cee98b8..181ed51 100644
--- a/core/java/com/android/server/backup/SystemBackupAgent.java
+++ b/core/java/com/android/server/backup/SystemBackupAgent.java
@@ -70,6 +70,8 @@
     private static final String WALLPAPER_IMAGE_KEY = WallpaperBackupHelper.WALLPAPER_IMAGE_KEY;
     private static final String WALLPAPER_INFO_KEY = WallpaperBackupHelper.WALLPAPER_INFO_KEY;
 
+    private WallpaperBackupHelper mWallpaperHelper = null;
+
     @Override
     public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
             ParcelFileDescriptor newState) throws IOException {
@@ -121,13 +123,16 @@
     @Override
     public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
             throws IOException {
-        // On restore, we also support a previous data schema "system_files"
-        addHelper(WALLPAPER_HELPER, new WallpaperBackupHelper(this,
+        mWallpaperHelper = new WallpaperBackupHelper(this,
                 new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO },
-                new String[] { WALLPAPER_IMAGE_KEY, WALLPAPER_INFO_KEY} ));
+                new String[] { WALLPAPER_IMAGE_KEY, WALLPAPER_INFO_KEY} );
+        addHelper(WALLPAPER_HELPER, mWallpaperHelper);
+
+        // On restore, we also support a previous data schema "system_files"
         addHelper("system_files", new WallpaperBackupHelper(this,
                 new String[] { WALLPAPER_IMAGE },
                 new String[] { WALLPAPER_IMAGE_KEY} ));
+
         addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this));
         addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper());
         addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this));
@@ -202,4 +207,9 @@
             }
         }
     }
+
+    @Override
+    public void onRestoreFinished() {
+        mWallpaperHelper.onRestoreFinished();
+    }
 }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 623b603..c6db0ed 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -36,7 +36,7 @@
     android_app_Activity.cpp \
     android_app_ApplicationLoaders.cpp \
     android_app_NativeActivity.cpp \
-    android_auditing_SecurityLog.cpp \
+    android_app_admin_SecurityLog.cpp \
     android_opengl_EGL14.cpp \
     android_opengl_EGLExt.cpp \
     android_opengl_GLES10.cpp \
@@ -161,6 +161,7 @@
     android_hardware_UsbDevice.cpp \
     android_hardware_UsbDeviceConnection.cpp \
     android_hardware_UsbRequest.cpp \
+    android_hardware_location_ContextHubService.cpp \
     android_hardware_location_ActivityRecognitionHardware.cpp \
     android_util_FileObserver.cpp \
     android/opengl/poly_clip.cpp.arm \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 2a04526..7ff38fd5 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -95,6 +95,7 @@
 extern int register_android_hardware_UsbDeviceConnection(JNIEnv *env);
 extern int register_android_hardware_UsbRequest(JNIEnv *env);
 extern int register_android_hardware_location_ActivityRecognitionHardware(JNIEnv* env);
+extern int register_android_hardware_location_ContextHubService(JNIEnv* env);
 
 extern int register_android_media_AudioRecord(JNIEnv *env);
 extern int register_android_media_AudioSystem(JNIEnv *env);
@@ -108,7 +109,7 @@
  * JNI-based registration functions.  Note these are properly contained in
  * namespace android.
  */
-extern int register_android_auditing_SecurityLog(JNIEnv* env);
+extern int register_android_app_admin_SecurityLog(JNIEnv* env);
 extern int register_android_content_AssetManager(JNIEnv* env);
 extern int register_android_util_EventLog(JNIEnv* env);
 extern int register_android_util_Log(JNIEnv* env);
@@ -1184,8 +1185,7 @@
     void** args = (void**) malloc(3 * sizeof(void*));   // javaThreadShell must free
     int result;
 
-    if (!threadName)
-        threadName = "unnamed thread";
+    LOG_ALWAYS_FATAL_IF(threadName == nullptr, "threadName not provided to javaCreateThreadEtc");
 
     args[0] = (void*) entryFunction;
     args[1] = userData;
@@ -1253,7 +1253,7 @@
     REG_JNI(register_android_util_EventLog),
     REG_JNI(register_android_util_Log),
     REG_JNI(register_android_util_PathParser),
-    REG_JNI(register_android_auditing_SecurityLog),
+    REG_JNI(register_android_app_admin_SecurityLog),
     REG_JNI(register_android_content_AssetManager),
     REG_JNI(register_android_content_StringBlock),
     REG_JNI(register_android_content_XmlBlock),
@@ -1358,6 +1358,7 @@
     REG_JNI(register_android_hardware_UsbDeviceConnection),
     REG_JNI(register_android_hardware_UsbRequest),
     REG_JNI(register_android_hardware_location_ActivityRecognitionHardware),
+    REG_JNI(register_android_hardware_location_ContextHubService),
     REG_JNI(register_android_media_AudioRecord),
     REG_JNI(register_android_media_AudioSystem),
     REG_JNI(register_android_media_AudioTrack),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 29c1075..4001283 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -73,6 +73,9 @@
         case SkEncodedFormat::kWBMP_SkEncodedFormat:
             mimeType = "image/vnd.wap.wbmp";
             break;
+        case SkEncodedFormat::kRAW_SkEncodedFormat:
+            mimeType = "image/x-adobe-dng";
+            break;
         default:
             mimeType = nullptr;
             break;
@@ -201,6 +204,26 @@
     const unsigned int mSize;
 };
 
+// Necessary for decodes when the native decoder cannot scale to appropriately match the sampleSize
+// (for example, RAW). If the sampleSize divides evenly into the dimension, we require that the
+// scale matches exactly. If sampleSize does not divide evenly, we allow the decoder to choose how
+// best to round.
+static bool needsFineScale(const int fullSize, const int decodedSize, const int sampleSize) {
+    if (fullSize % sampleSize == 0 && fullSize / sampleSize != decodedSize) {
+        return true;
+    } else if ((fullSize / sampleSize + 1) != decodedSize &&
+               (fullSize / sampleSize) != decodedSize) {
+        return true;
+    }
+    return false;
+}
+
+static bool needsFineScale(const SkISize fullSize, const SkISize decodedSize,
+                           const int sampleSize) {
+    return needsFineScale(fullSize.width(), decodedSize.width(), sampleSize) ||
+           needsFineScale(fullSize.height(), decodedSize.height(), sampleSize);
+}
+
 static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding, jobject options) {
     // This function takes ownership of the input stream.  Since the SkAndroidCodec
     // will take ownership of the stream, we don't necessarily need to take ownership
@@ -250,7 +273,6 @@
             }
         }
     }
-    const bool willScale = scale != 1.0f;
 
     // Create the codec.
     NinePatchPeeker peeker;
@@ -269,15 +291,28 @@
         prefColorType = kN32_SkColorType;
     }
 
-    // Determine the output size and return if the client only wants the size.
+    // Determine the output size.
     SkISize size = codec->getSampledDimensions(sampleSize);
+
+    int scaledWidth = size.width();
+    int scaledHeight = size.height();
+    bool willScale = false;
+
+    // Apply a fine scaling step if necessary.
+    if (needsFineScale(codec->getInfo().dimensions(), size, sampleSize)) {
+        willScale = true;
+        scaledWidth = codec->getInfo().width() / sampleSize;
+        scaledHeight = codec->getInfo().height() / sampleSize;
+    }
+
+    // Set the options and return if the client only wants the size.
     if (options != NULL) {
         jstring mimeType = encodedFormatToString(env, codec->getEncodedFormat());
         if (env->ExceptionCheck()) {
             return nullObjectReturn("OOM in encodedFormatToString()");
         }
-        env->SetIntField(options, gOptions_widthFieldID, size.width());
-        env->SetIntField(options, gOptions_heightFieldID, size.height());
+        env->SetIntField(options, gOptions_widthFieldID, scaledWidth);
+        env->SetIntField(options, gOptions_heightFieldID, scaledHeight);
         env->SetObjectField(options, gOptions_mimeFieldID, mimeType);
 
         if (onlyDecodeSize) {
@@ -285,6 +320,13 @@
         }
     }
 
+    // Scale is necessary due to density differences.
+    if (scale != 1.0f) {
+        willScale = true;
+        scaledWidth = static_cast<int>(scaledWidth * scale + 0.5f);
+        scaledHeight = static_cast<int>(scaledHeight * scale + 0.5f);
+    }
+
     android::Bitmap* reuseBitmap = nullptr;
     unsigned int existingBufferSize = 0;
     if (javaBitmap != NULL) {
@@ -381,13 +423,6 @@
             return nullObjectReturn("codec->getAndroidPixels() failed.");
     }
 
-    int scaledWidth = size.width();
-    int scaledHeight = size.height();
-    if (willScale) {
-        scaledWidth = int(scaledWidth * scale + 0.5f);
-        scaledHeight = int(scaledHeight * scale + 0.5f);
-    }
-
     jbyteArray ninePatchChunk = NULL;
     if (peeker.mPatch != NULL) {
         if (willScale) {
diff --git a/core/jni/android/graphics/Xfermode.cpp b/core/jni/android/graphics/Xfermode.cpp
index 7441acc..78975a4f 100644
--- a/core/jni/android/graphics/Xfermode.cpp
+++ b/core/jni/android/graphics/Xfermode.cpp
@@ -15,34 +15,20 @@
  */
 
 #include "jni.h"
-#include "GraphicsJNI.h"
+//#include "GraphicsJNI.h"
 #include "core_jni_helpers.h"
 
-#include "AvoidXfermode.h"
-#include "SkPixelXorXfermode.h"
+#include <SkXfermode.h>
 
 namespace android {
 
 class SkXfermodeGlue {
 public:
-
     static void finalizer(JNIEnv* env, jobject, jlong objHandle)
     {
         SkXfermode* obj = reinterpret_cast<SkXfermode *>(objHandle);
         SkSafeUnref(obj);
     }
-    
-    static jlong avoid_create(JNIEnv* env, jobject, jint opColor,
-                                jint tolerance, jint modeHandle)
-    {
-        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)
-    {
-        return reinterpret_cast<jlong>(SkPixelXorXfermode::Create(opColor));
-    }
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -51,24 +37,9 @@
     {"finalizer", "(J)V", (void*) SkXfermodeGlue::finalizer}
 };
 
-static const JNINativeMethod gAvoidMethods[] = {
-    {"nativeCreate", "(III)J", (void*) SkXfermodeGlue::avoid_create}
-};
-
-static const JNINativeMethod gPixelXorMethods[] = {
-    {"nativeCreate", "(I)J", (void*) SkXfermodeGlue::pixelxor_create}
-};
-
 int register_android_graphics_Xfermode(JNIEnv* env) {
     android::RegisterMethodsOrDie(env, "android/graphics/Xfermode", gXfermodeMethods,
                                   NELEM(gXfermodeMethods));
-    android::RegisterMethodsOrDie(env, "android/graphics/Xfermode", gXfermodeMethods,
-                                  NELEM(gXfermodeMethods));
-    android::RegisterMethodsOrDie(env, "android/graphics/AvoidXfermode", gAvoidMethods,
-                                  NELEM(gAvoidMethods));
-    android::RegisterMethodsOrDie(env, "android/graphics/PixelXorXfermode", gPixelXorMethods,
-                                  NELEM(gPixelXorMethods));
-
     return 0;
 }
 
diff --git a/core/jni/android_app_admin_SecurityLog.cpp b/core/jni/android_app_admin_SecurityLog.cpp
new file mode 100644
index 0000000..da47c4c
--- /dev/null
+++ b/core/jni/android_app_admin_SecurityLog.cpp
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2016 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 <fcntl.h>
+
+#include "JNIHelp.h"
+#include "core_jni_helpers.h"
+#include "jni.h"
+#include "log/logger.h"
+
+// The size of the tag number comes out of the payload size.
+#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
+
+namespace android {
+
+static jclass gCollectionClass;
+static jmethodID gCollectionAddID;
+
+static jclass gEventClass;
+static jmethodID gEventInitID;
+
+static jclass gIntegerClass;
+static jfieldID gIntegerValueID;
+
+static jclass gLongClass;
+static jfieldID gLongValueID;
+
+static jclass gFloatClass;
+static jfieldID gFloatValueID;
+
+static jclass gStringClass;
+
+
+static jboolean android_app_admin_SecurityLog_isLoggingEnabled(JNIEnv* env,
+                                                    jobject /* clazz */) {
+    return (bool)__android_log_security();
+}
+
+static jint android_app_admin_SecurityLog_writeEvent_String(JNIEnv* env,
+                                                    jobject /* clazz */,
+                                                    jint tag, jstring value) {
+    uint8_t buf[MAX_EVENT_PAYLOAD];
+
+    // Don't throw NPE -- I feel like it's sort of mean for a logging function
+    // to be all crashy if you pass in NULL -- but make the NULL value explicit.
+    const char *str = value != NULL ? env->GetStringUTFChars(value, NULL) : "NULL";
+    uint32_t len = strlen(str);
+    size_t max = sizeof(buf) - sizeof(len) - 2;  // Type byte, final newline
+    if (len > max) len = max;
+
+    buf[0] = EVENT_TYPE_STRING;
+    memcpy(&buf[1], &len, sizeof(len));
+    memcpy(&buf[1 + sizeof(len)], str, len);
+    buf[1 + sizeof(len) + len] = '\n';
+
+    if (value != NULL) env->ReleaseStringUTFChars(value, str);
+    return __android_log_security_bwrite(tag, buf, 2 + sizeof(len) + len);
+}
+
+static jint android_app_admin_SecurityLog_writeEvent_Array(JNIEnv* env, jobject clazz,
+                                                   jint tag, jobjectArray value) {
+    if (value == NULL) {
+        return android_app_admin_SecurityLog_writeEvent_String(env, clazz, tag, NULL);
+    }
+
+    uint8_t buf[MAX_EVENT_PAYLOAD];
+    const size_t max = sizeof(buf) - 1;  // leave room for final newline
+    size_t pos = 2;  // Save room for type tag & array count
+
+    jsize copied = 0, num = env->GetArrayLength(value);
+    for (; copied < num && copied < 255; ++copied) {
+        jobject item = env->GetObjectArrayElement(value, copied);
+        if (item == NULL || env->IsInstanceOf(item, gStringClass)) {
+            if (pos + 1 + sizeof(jint) > max) break;
+            const char *str = item != NULL ? env->GetStringUTFChars((jstring) item, NULL) : "NULL";
+            jint len = strlen(str);
+            if (pos + 1 + sizeof(len) + len > max) len = max - pos - 1 - sizeof(len);
+            buf[pos++] = EVENT_TYPE_STRING;
+            memcpy(&buf[pos], &len, sizeof(len));
+            memcpy(&buf[pos + sizeof(len)], str, len);
+            pos += sizeof(len) + len;
+            if (item != NULL) env->ReleaseStringUTFChars((jstring) item, str);
+        } else if (env->IsInstanceOf(item, gIntegerClass)) {
+            jint intVal = env->GetIntField(item, gIntegerValueID);
+            if (pos + 1 + sizeof(intVal) > max) break;
+            buf[pos++] = EVENT_TYPE_INT;
+            memcpy(&buf[pos], &intVal, sizeof(intVal));
+            pos += sizeof(intVal);
+        } else if (env->IsInstanceOf(item, gLongClass)) {
+            jlong longVal = env->GetLongField(item, gLongValueID);
+            if (pos + 1 + sizeof(longVal) > max) break;
+            buf[pos++] = EVENT_TYPE_LONG;
+            memcpy(&buf[pos], &longVal, sizeof(longVal));
+            pos += sizeof(longVal);
+        } else if (env->IsInstanceOf(item, gFloatClass)) {
+            jfloat floatVal = env->GetFloatField(item, gFloatValueID);
+            if (pos + 1 + sizeof(floatVal) > max) break;
+            buf[pos++] = EVENT_TYPE_FLOAT;
+            memcpy(&buf[pos], &floatVal, sizeof(floatVal));
+            pos += sizeof(floatVal);
+        } else {
+            jniThrowException(env,
+                    "java/lang/IllegalArgumentException",
+                    "Invalid payload item type");
+            return -1;
+        }
+        env->DeleteLocalRef(item);
+    }
+
+    buf[0] = EVENT_TYPE_LIST;
+    buf[1] = copied;
+    buf[pos++] = '\n';
+    return __android_log_security_bwrite(tag, buf, pos);
+}
+
+static void readEvents(JNIEnv* env, int loggerMode, jlong startTime, jobject out) {
+    struct logger_list *logger_list;
+    if (startTime) {
+        logger_list = android_logger_list_alloc_time(loggerMode,
+                log_time(startTime / NS_PER_SEC, startTime % NS_PER_SEC), 0);
+    } else {
+        logger_list = android_logger_list_alloc(loggerMode, 0, 0);
+    }
+    if (!logger_list) {
+        jniThrowIOException(env, errno);
+        return;
+    }
+
+    if (!android_logger_open(logger_list, LOG_ID_SECURITY)) {
+        jniThrowIOException(env, errno);
+        android_logger_list_free(logger_list);
+        return;
+    }
+
+    while (1) {
+        log_msg log_msg;
+        int ret = android_logger_list_read(logger_list, &log_msg);
+
+        if (ret == 0) {
+            break;
+        }
+        if (ret < 0) {
+            if (ret == -EINTR) {
+                continue;
+            }
+            if (ret == -EINVAL) {
+                jniThrowException(env, "java/io/IOException", "Event too short");
+            } else if (ret != -EAGAIN) {
+                jniThrowIOException(env, -ret);  // Will throw on return
+            }
+            break;
+        }
+
+        if (log_msg.id() != LOG_ID_SECURITY) {
+            continue;
+        }
+
+        jsize len = ret;
+        jbyteArray array = env->NewByteArray(len);
+        if (array == NULL) {
+            break;
+        }
+
+        jbyte *bytes = env->GetByteArrayElements(array, NULL);
+        memcpy(bytes, log_msg.buf, len);
+        env->ReleaseByteArrayElements(array, bytes, 0);
+
+        jobject event = env->NewObject(gEventClass, gEventInitID, array);
+        if (event == NULL) {
+            break;
+        }
+
+        env->CallBooleanMethod(out, gCollectionAddID, event);
+        env->DeleteLocalRef(event);
+        env->DeleteLocalRef(array);
+    }
+
+    android_logger_list_close(logger_list);
+}
+
+static void android_app_admin_SecurityLog_readEvents(JNIEnv* env, jobject /* clazz */,
+                                             jobject out) {
+
+    if (out == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, out);
+}
+
+static void android_app_admin_SecurityLog_readEventsSince(JNIEnv* env, jobject /* clazz */,
+                                             jlong timestamp,
+                                             jobject out) {
+
+    if (out == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, timestamp, out);
+}
+
+static void android_app_admin_SecurityLog_readPreviousEvents(JNIEnv* env, jobject /* clazz */,
+                                             jobject out) {
+
+    if (out == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_PSTORE, 0, out);
+}
+
+static void android_app_admin_SecurityLog_readEventsOnWrapping(JNIEnv* env, jobject /* clazz */,
+                                             jlong timestamp,
+                                             jobject out) {
+    if (out == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return;
+    }
+    readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_WRAP, timestamp, out);
+}
+
+/*
+ * JNI registration.
+ */
+static const JNINativeMethod gRegisterMethods[] = {
+    /* name, signature, funcPtr */
+    { "isLoggingEnabled",
+      "()Z",
+      (void*) android_app_admin_SecurityLog_isLoggingEnabled
+    },
+    { "writeEvent",
+      "(ILjava/lang/String;)I",
+      (void*) android_app_admin_SecurityLog_writeEvent_String
+    },
+    { "writeEvent",
+      "(I[Ljava/lang/Object;)I",
+      (void*) android_app_admin_SecurityLog_writeEvent_Array
+    },
+    { "readEvents",
+      "(Ljava/util/Collection;)V",
+      (void*) android_app_admin_SecurityLog_readEvents
+    },
+    { "readEventsSince",
+      "(JLjava/util/Collection;)V",
+      (void*) android_app_admin_SecurityLog_readEventsSince
+    },
+    { "readPreviousEvents",
+      "(Ljava/util/Collection;)V",
+      (void*) android_app_admin_SecurityLog_readPreviousEvents
+    },
+    { "readEventsOnWrapping",
+      "(JLjava/util/Collection;)V",
+      (void*) android_app_admin_SecurityLog_readEventsOnWrapping
+    },
+};
+
+static struct { const char *name; jclass *clazz; } gClasses[] = {
+    { "android/app/admin/SecurityLog$SecurityEvent", &gEventClass },
+    { "java/lang/Integer", &gIntegerClass },
+    { "java/lang/Long", &gLongClass },
+    { "java/lang/Float", &gFloatClass },
+    { "java/lang/String", &gStringClass },
+    { "java/util/Collection", &gCollectionClass },
+};
+
+static struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = {
+    { &gIntegerClass, "value", "I", &gIntegerValueID },
+    { &gLongClass, "value", "J", &gLongValueID },
+    { &gFloatClass, "value", "F", &gFloatValueID },
+};
+
+static struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = {
+    { &gEventClass, "<init>", "([B)V", &gEventInitID },
+    { &gCollectionClass, "add", "(Ljava/lang/Object;)Z", &gCollectionAddID },
+};
+
+int register_android_app_admin_SecurityLog(JNIEnv* env) {
+    for (int i = 0; i < NELEM(gClasses); ++i) {
+        jclass clazz = FindClassOrDie(env, gClasses[i].name);
+        *gClasses[i].clazz = MakeGlobalRefOrDie(env, clazz);
+    }
+
+    for (int i = 0; i < NELEM(gFields); ++i) {
+        *gFields[i].id = GetFieldIDOrDie(env,
+                *gFields[i].c, gFields[i].name, gFields[i].ft);
+    }
+
+    for (int i = 0; i < NELEM(gMethods); ++i) {
+        *gMethods[i].id = GetMethodIDOrDie(env,
+                *gMethods[i].c, gMethods[i].name, gMethods[i].mt);
+    }
+
+    return RegisterMethodsOrDie(
+            env,
+            "android/app/admin/SecurityLog",
+            gRegisterMethods, NELEM(gRegisterMethods));
+}
+
+}; // namespace android
diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp
index 7314fbc..e17de17 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -78,11 +78,11 @@
 static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong fullPathPtr,
         jfloat strokeWidth, jint strokeColor, jfloat strokeAlpha, jint fillColor, jfloat fillAlpha,
         jfloat trimPathStart, jfloat trimPathEnd, jfloat trimPathOffset, jfloat strokeMiterLimit,
-        jint strokeLineCap, jint strokeLineJoin) {
+        jint strokeLineCap, jint strokeLineJoin, jint fillType) {
     VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr);
     fullPath->updateProperties(strokeWidth, strokeColor, strokeAlpha, fillColor, fillAlpha,
             trimPathStart, trimPathEnd, trimPathOffset, strokeMiterLimit, strokeLineCap,
-            strokeLineJoin);
+            strokeLineJoin, fillType);
 }
 
 static void updateFullPathFillGradient(JNIEnv*, jobject, jlong pathPtr, jlong fillGradientPtr) {
@@ -331,7 +331,7 @@
         {"nDraw", "(JJJLandroid/graphics/Rect;ZZ)V", (void*)draw},
         {"nCreateFullPath", "!()J", (void*)createEmptyFullPath},
         {"nCreateFullPath", "!(J)J", (void*)createFullPath},
-        {"nUpdateFullPathProperties", "!(JFIFIFFFFFII)V", (void*)updateFullPathPropertiesAndStrokeStyles},
+        {"nUpdateFullPathProperties", "!(JFIFIFFFFFIII)V", (void*)updateFullPathPropertiesAndStrokeStyles},
         {"nUpdateFullPathFillGradient", "!(JJ)V", (void*)updateFullPathFillGradient},
         {"nUpdateFullPathStrokeGradient", "!(JJ)V", (void*)updateFullPathStrokeGradient},
         {"nGetFullPathProperties", "(J[BI)Z", (void*)getFullPathProperties},
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index c6baf1c..d80d8f2 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 #define LOG_TAG "DngCreator_JNI"
 #include <inttypes.h>
 #include <string.h>
@@ -1792,6 +1792,8 @@
 
     {
         // Set up orientation tags.
+        // Note: There's only one orientation field for the whole file, in IFD0
+        // The main image and any thumbnails therefore have the same orientation.
         uint16_t orientation = nativeContext->getOrientation();
         BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_ORIENTATION, 1, &orientation, TIFF_IFD_0),
                 env, TAG_ORIENTATION, writer);
@@ -1873,7 +1875,6 @@
         }
 
         Vector<uint16_t> tagsToMove;
-        tagsToMove.add(TAG_ORIENTATION);
         tagsToMove.add(TAG_NEWSUBFILETYPE);
         tagsToMove.add(TAG_ACTIVEAREA);
         tagsToMove.add(TAG_BITSPERSAMPLE);
@@ -1904,12 +1905,6 @@
             return nullptr;
         }
 
-        // Make sure both IFDs get the same orientation tag
-        sp<TiffEntry> orientEntry = writer->getEntry(TAG_ORIENTATION, TIFF_IFD_SUB1);
-        if (orientEntry.get() != nullptr) {
-            writer->addEntry(orientEntry, TIFF_IFD_0);
-        }
-
         // Setup thumbnail tags
 
         {
diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp
new file mode 100644
index 0000000..8724729
--- /dev/null
+++ b/core/jni/android_hardware_location_ContextHubService.cpp
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2016, 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 "context_hub.h"
+
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <jni.h>
+#include "JNIHelp.h"
+#include "core_jni_helpers.h"
+#include "stdint.h"
+#include "stdlib.h"
+
+
+namespace android {
+
+namespace {
+
+// TODO: We should share this array_length function widely around Android
+//     code.
+/*
+ * Finds the length of a statically-sized array using template trickery that
+ * also prevents it from being applied to the wrong type.
+ */
+template <typename T, size_t N>
+constexpr size_t array_length(T (&)[N]) { return N; }
+
+struct jniInfo_s {
+    JavaVM *vm;
+    jclass contextHubInfoClass;
+    jclass contextHubServiceClass;
+    jclass memoryRegionsClass;
+
+    jobject jContextHubService;
+
+    jmethodID msgReceiptCallBack;
+
+    jmethodID contextHubInfoCtor;
+    jmethodID contextHubInfoSetId;
+    jmethodID contextHubInfoSetName;
+    jmethodID contextHubInfoSetVendor;
+    jmethodID contextHubInfoSetToolchain;
+    jmethodID contextHubInfoSetPlatformVersion;
+    jmethodID contextHubInfoSetStaticSwVersion;
+    jmethodID contextHubInfoSetToolchainVersion;
+    jmethodID contextHubInfoSetPeakMips;
+    jmethodID contextHubInfoSetStoppedPowerDrawMw;
+    jmethodID contextHubInfoSetSleepPowerDrawMw;
+    jmethodID contextHubInfoSetPeakPowerDrawMw;
+    jmethodID contextHubInfoSetSupportedSensors;
+    jmethodID contextHubInfoSetMemoryRegions;
+
+    jmethodID contextHubServiceMsgReceiptCallback;
+};
+
+struct context_hub_info_s {
+    int cookie;
+    int numHubs;
+    const struct context_hub_t *hubs;
+    struct context_hub_module_t *contextHubModule;
+};
+
+struct contextHubServiceDb_s {
+    int initialized;
+    context_hub_info_s hubInfo;
+    jniInfo_s jniInfo;
+};
+
+}  // unnamed namespace
+
+static contextHubServiceDb_s db;
+
+int context_hub_callback(uint32_t hub_id, const struct hub_message_t *msg,
+                         void *cookie);
+
+static void initContextHubService() {
+    int err = 0;
+    db.hubInfo.hubs = NULL;
+    db.hubInfo.numHubs = 0;
+    db.hubInfo.cookie = 0;
+    int i;
+
+    err = hw_get_module(CONTEXT_HUB_MODULE_ID,
+                        (hw_module_t const**)(&db.hubInfo.contextHubModule));
+
+    if (err) {
+      ALOGE("** Could not load %s module : err %s", CONTEXT_HUB_MODULE_ID,
+            strerror(-err));
+    }
+
+    if (db.hubInfo.contextHubModule) {
+      ALOGD("Fetching hub info");
+      db.hubInfo.numHubs = db.hubInfo.contextHubModule->get_hubs(db.hubInfo.contextHubModule,
+                                                                 &db.hubInfo.hubs);
+
+      if (db.hubInfo.numHubs > 0) {
+        for (i = 0; i < db.hubInfo.numHubs; i++) {
+          // TODO : Event though one cookie is OK for now, lets change
+          // this to be one per hub
+          db.hubInfo.contextHubModule->subscribe_messages(db.hubInfo.hubs[i].hub_id,
+                                                          context_hub_callback,
+                                                          &db.hubInfo.cookie);
+        }
+      }
+    }
+}
+
+static int onMessageReceipt(int *header, int headerLen, char *msg, int msgLen) {
+    JNIEnv *env;
+    if ((db.jniInfo.vm)->AttachCurrentThread(&env, NULL) != JNI_OK) {
+      return -1;
+    }
+
+    jbyteArray jmsg = env->NewByteArray(msgLen);
+    jintArray jheader = env->NewIntArray(headerLen);
+
+    env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg);
+    env->SetIntArrayRegion(jheader, 0, headerLen, (jint *)header);
+
+
+    return env->CallIntMethod(db.jniInfo.jContextHubService,
+                          db.jniInfo.contextHubServiceMsgReceiptCallback,
+                          jheader, jmsg);
+}
+
+int context_hub_callback(uint32_t hub_id, const struct hub_message_t *msg,
+                         void *cookie) {
+  int msgHeader[4];
+
+  msgHeader[0] = msg->message_type;
+  msgHeader[1] = 0; // TODO : HAL does not have a version field
+  msgHeader[2] = hub_id;
+
+  onMessageReceipt(msgHeader, sizeof(msgHeader), (char *)msg->message, msg->message_len); // TODO : Populate this
+  return 0;
+}
+
+static int init_jni(JNIEnv *env, jobject instance) {
+
+    if (env->GetJavaVM(&db.jniInfo.vm) != JNI_OK) {
+      return -1;
+    }
+
+    db.jniInfo.jContextHubService = env->NewGlobalRef(instance);
+
+    db.jniInfo.contextHubInfoClass =
+            env->FindClass("android/hardware/location/ContextHubInfo");
+
+    db.jniInfo.contextHubServiceClass =
+            env->FindClass("android/hardware/location/ContextHubService");
+
+    db.jniInfo.memoryRegionsClass =
+            env->FindClass("android/hardware/location/MemoryRegion");
+
+    //TODO :: Add error checking
+    db.jniInfo.contextHubInfoCtor =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass, "<init>", "()V");
+    db.jniInfo.contextHubInfoSetId =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass, "setId", "(I)V");
+    db.jniInfo.contextHubInfoSetName =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass, "setName",
+                                "(Ljava/lang/String;)V");
+
+    db.jniInfo.contextHubInfoSetVendor =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass,
+                                "setVendor", "(Ljava/lang/String;)V");
+    db.jniInfo.contextHubInfoSetToolchain =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass,
+                                "setToolchain", "(Ljava/lang/String;)V");
+    db.jniInfo.contextHubInfoSetPlatformVersion =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass,
+                                "setPlatformVersion", "(I)V");
+    db.jniInfo.contextHubInfoSetStaticSwVersion =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass,
+                                "setStaticSwVersion", "(I)V");
+    db.jniInfo.contextHubInfoSetToolchainVersion =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass,
+                                "setToolchainVersion", "(I)V");
+    db.jniInfo.contextHubInfoSetPeakMips =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass,
+                                "setPeakMips", "(F)V");
+    db.jniInfo.contextHubInfoSetStoppedPowerDrawMw =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass,
+                                "setStoppedPowerDrawMw", "(F)V");
+    db.jniInfo.contextHubInfoSetSleepPowerDrawMw =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass,
+                                "setSleepPowerDrawMw", "(F)V");
+    db.jniInfo.contextHubInfoSetPeakPowerDrawMw =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass,
+                                "setPeakPowerDrawMw", "(F)V");
+    db.jniInfo.contextHubInfoSetSupportedSensors =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass,
+                                "setSupportedSensors", "([I)V");
+    db.jniInfo.contextHubInfoSetMemoryRegions =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass,
+                                "setMemoryRegions", "([Landroid/hardware/location/MemoryRegion;)V");
+
+
+    db.jniInfo.contextHubServiceMsgReceiptCallback =
+            env->GetMethodID(db.jniInfo.contextHubServiceClass, "onMessageReceipt",
+                               "([I[B)I");
+    db.jniInfo.contextHubInfoSetName =
+            env->GetMethodID(db.jniInfo.contextHubInfoClass, "setName",
+            "(Ljava/lang/String;)V");
+
+
+    return 0;
+}
+
+static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t *hub) {
+    jstring jstrBuf;
+    jintArray jintBuf;
+    jobjectArray jmemBuf;
+
+    int dummyConnectedSensors[] = {1, 2, 3, 4, 5};
+
+    jobject jHub = env->NewObject(db.jniInfo.contextHubInfoClass,
+                                  db.jniInfo.contextHubInfoCtor);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetId, hub->hub_id);
+
+    jstrBuf = env->NewStringUTF(hub->name);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetName, jstrBuf);
+
+    jstrBuf = env->NewStringUTF(hub->vendor);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetVendor, jstrBuf);
+
+    jstrBuf = env->NewStringUTF(hub->toolchain);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchain, jstrBuf);
+
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPlatformVersion, hub->platform_version);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchainVersion, hub->toolchain_version);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakMips, hub->peak_mips);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetStoppedPowerDrawMw, hub->stopped_power_draw_mw);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSleepPowerDrawMw, hub->sleep_power_draw_mw);
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakPowerDrawMw, hub->peak_power_draw_mw);
+
+    // TODO : jintBuf = env->NewIntArray(hub->num_connected_sensors);
+    // TODO : env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, hub->connected_sensors);
+    jintBuf = env->NewIntArray(array_length(dummyConnectedSensors));
+    env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, dummyConnectedSensors);
+
+    // We are not getting the memory regions from the CH Hal - change this when it is available
+    jmemBuf = env->NewObjectArray(0, db.jniInfo.memoryRegionsClass, NULL);
+    // Note the zero size above. We do not need to set any elements
+    env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetMemoryRegions, jmemBuf);
+
+    return jHub;
+}
+
+static jobjectArray nativeInitialize(JNIEnv *env, jobject instance)
+{
+    jobject hub;
+    jobjectArray retArray;
+
+    initContextHubService();
+
+    if (init_jni(env, instance) < 0) {
+        return NULL;
+    }
+
+    // Note : The service is clamping the number of hubs to 1
+    db.hubInfo.numHubs = 1;
+
+    initContextHubService();
+
+    retArray = env->NewObjectArray(db.hubInfo.numHubs, db.jniInfo.contextHubInfoClass, NULL);
+
+    for(int i = 0; i < db.hubInfo.numHubs; i++) {
+        hub = constructJContextHubInfo(env, &db.hubInfo.hubs[i]);
+        env->SetObjectArrayElement(retArray, i, hub);
+    }
+
+    return retArray;
+}
+
+static jint nativeSendMessage(JNIEnv *env, jobject instance, jintArray header_,
+                              jbyteArray data_) {
+    hub_message_t msg;
+    hub_app_name_t dest;
+    uint8_t os_name[8];
+
+    memset(os_name, 0, sizeof(os_name));
+
+    jint *header = env->GetIntArrayElements(header_, 0);
+    //int numHeaderElements = env->GetArrayLength(header_);
+    jbyte *data = env->GetByteArrayElements(data_, 0);
+    int dataBufferLength = env->GetArrayLength(data_);
+
+    /* Assume an int - thats all we understand */
+    dest.app_name_len = array_length(os_name); // TODO : Check this
+    //dest.app_name = &header[1];
+    dest.app_name = os_name;
+
+    msg.app = &dest;
+
+    msg.message_type = header[3];
+    msg.message_len = dataBufferLength;
+    msg.message = data;
+
+    jint retVal = db.hubInfo.contextHubModule->send_message(header[0], &msg);
+
+    env->ReleaseIntArrayElements(header_, header, 0);
+    env->ReleaseByteArrayElements(data_, data, 0);
+
+    return retVal;
+}
+
+//--------------------------------------------------------------------------------------------------
+//
+static const JNINativeMethod gContextHubServiceMethods[] = {
+    {"nativeInitialize",
+             "()[Landroid/hardware/location/ContextHubInfo;",
+             (void*)nativeInitialize },
+    {"nativeSendMessage",
+            "([I[B)I",
+            (void*)nativeSendMessage }
+};
+
+}//namespace android
+
+using namespace android;
+
+int register_android_hardware_location_ContextHubService(JNIEnv *env)
+{
+    RegisterMethodsOrDie(env, "android/hardware/location/ContextHubService",
+            gContextHubServiceMethods, NELEM(gContextHubServiceMethods));
+
+    return 0;
+}
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 9d15019..7496124 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -109,7 +109,8 @@
     jfieldID    mRule;
     jfieldID    mFormat;
     jfieldID    mRouteFlags;
-    jfieldID    mRegistrationId;
+    jfieldID    mDeviceType;
+    jfieldID    mDeviceAddress;
     jfieldID    mMixType;
     jfieldID    mCallbackFlags;
 } gAudioMixFields;
@@ -1561,13 +1562,15 @@
 {
     nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
     nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
+    nAudioMix->mDeviceType = (audio_devices_t)
+            env->GetIntField(jAudioMix, gAudioMixFields.mDeviceType);
 
-    jstring jRegistrationId = (jstring)env->GetObjectField(jAudioMix,
-                                                           gAudioMixFields.mRegistrationId);
-    const char *nRegistrationId = env->GetStringUTFChars(jRegistrationId, NULL);
-    nAudioMix->mRegistrationId = String8(nRegistrationId);
-    env->ReleaseStringUTFChars(jRegistrationId, nRegistrationId);
-    env->DeleteLocalRef(jRegistrationId);
+    jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioMix,
+                                                           gAudioMixFields.mDeviceAddress);
+    const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
+    nAudioMix->mDeviceAddress = String8(nDeviceAddress);
+    env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress);
+    env->DeleteLocalRef(jDeviceAddress);
 
     nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
 
@@ -1857,7 +1860,8 @@
     gAudioMixFields.mFormat = GetFieldIDOrDie(env, audioMixClass, "mFormat",
                                                 "Landroid/media/AudioFormat;");
     gAudioMixFields.mRouteFlags = GetFieldIDOrDie(env, audioMixClass, "mRouteFlags", "I");
-    gAudioMixFields.mRegistrationId = GetFieldIDOrDie(env, audioMixClass, "mRegistrationId",
+    gAudioMixFields.mDeviceType = GetFieldIDOrDie(env, audioMixClass, "mDeviceSystemType", "I");
+    gAudioMixFields.mDeviceAddress = GetFieldIDOrDie(env, audioMixClass, "mDeviceAddress",
                                                       "Ljava/lang/String;");
     gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I");
     gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I");
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index b7701d6..14252dc 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -144,7 +144,7 @@
         PublicFormat f) {
     switch(f) {
         case PublicFormat::JPEG:
-            return HAL_DATASPACE_JFIF;
+            return HAL_DATASPACE_V0_JFIF;
         case PublicFormat::DEPTH_POINT_CLOUD:
         case PublicFormat::DEPTH16:
             return HAL_DATASPACE_DEPTH;
@@ -156,7 +156,7 @@
         case PublicFormat::YUV_420_888:
         case PublicFormat::NV21:
         case PublicFormat::YV12:
-            return HAL_DATASPACE_JFIF;
+            return HAL_DATASPACE_V0_JFIF;
         default:
             // Most formats map to UNKNOWN
             return HAL_DATASPACE_UNKNOWN;
@@ -210,7 +210,7 @@
             switch (dataSpace) {
                 case HAL_DATASPACE_DEPTH:
                     return PublicFormat::DEPTH_POINT_CLOUD;
-                case HAL_DATASPACE_JFIF:
+                case HAL_DATASPACE_V0_JFIF:
                     return PublicFormat::JPEG;
                 default:
                     // Assume otherwise-marked blobs are also JPEG
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index fbc96c2..6444c6c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1483,11 +1483,21 @@
 
     <!-- Allows an application to manage access to documents, usually as part
          of a document picker.
+         <p>This permission should <em>only</em> be requested by the platform
+         document management app.  This permission cannot be granted to
+         third-party apps.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.MANAGE_DOCUMENTS"
         android:protectionLevel="signature" />
 
+    <!-- @hide Allows an application to cache content.
+         <p>Not for use by third-party applications.
+         <p>Protection level: signature
+    -->
+    <permission android:name="android.permission.CACHE_CONTENT"
+        android:protectionLevel="signature" />
+
     <!-- ================================== -->
     <!-- Permissions for screenlock         -->
     <!-- ================================== -->
diff --git a/core/res/res/anim/lock_screen_behind_enter.xml b/core/res/res/anim/lock_screen_behind_enter.xml
index 6f3c4d42..c96e280 100644
--- a/core/res/res/anim/lock_screen_behind_enter.xml
+++ b/core/res/res/anim/lock_screen_behind_enter.xml
@@ -16,7 +16,6 @@
   -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:background="#ff000000"
         android:detachWallpaper="true"
         android:shareInterpolator="false"
         android:startOffset="100">
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index b8b00bf..0bbaa24 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -20,9 +20,9 @@
     android:id="@+id/notification_header"
     android:orientation="horizontal"
     android:layout_width="wrap_content"
-    android:layout_height="48dp"
+    android:layout_height="53dp"
     android:clipChildren="false"
-    android:paddingTop="5dp"
+    android:paddingTop="10dp"
     android:paddingBottom="16dp"
     android:paddingStart="@dimen/notification_content_margin_start"
     android:paddingEnd="16dp">
diff --git a/core/res/res/layout/notification_template_material_base.xml b/core/res/res/layout/notification_template_material_base.xml
index a37bfa9..ccd26fb 100644
--- a/core/res/res/layout/notification_template_material_base.xml
+++ b/core/res/res/layout/notification_template_material_base.xml
@@ -41,7 +41,7 @@
         android:layout_height="wrap_content"
         android:layout_gravity="bottom"
         android:layout_marginStart="@dimen/notification_content_margin_start"
-        android:layout_marginBottom="11dp"
+        android:layout_marginBottom="15dp"
         android:layout_marginEnd="@dimen/notification_content_margin_end" >
         <include layout="@layout/notification_template_progress" />
     </FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml
index f302087..d53fb5f 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -49,7 +49,7 @@
             android:layout_height="wrap_content"
             android:layout_gravity="bottom"
             android:layout_marginStart="@dimen/notification_content_margin_start"
-            android:layout_marginBottom="11dp"
+            android:layout_marginBottom="15dp"
             android:layout_marginEnd="@dimen/notification_content_margin_end">
             <include layout="@layout/notification_template_progress" />
         </FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml
index a5ed187..04ea12d 100644
--- a/core/res/res/layout/notification_template_material_big_media.xml
+++ b/core/res/res/layout/notification_template_material_big_media.xml
@@ -25,7 +25,7 @@
     >
     <include layout="@layout/notification_template_header"
         android:layout_width="match_parent"
-        android:layout_height="48dp"
+        android:layout_height="53dp"
         android:layout_gravity="start"/>
     <LinearLayout
         android:layout_width="match_parent"
@@ -50,9 +50,10 @@
             android:id="@+id/media_actions"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginTop="-15dp"
+            android:layout_marginTop="-21dp"
             android:paddingStart="8dp"
-            android:paddingBottom="8dp"
+            android:paddingBottom="12dp"
+            android:gravity="top"
             android:orientation="horizontal"
             android:layoutDirection="ltr"
             >
@@ -65,7 +66,7 @@
         android:layout_height="@dimen/media_notification_expanded_image_max_size"
         android:minWidth="40dp"
         android:layout_marginEnd="16dp"
-        android:layout_marginBottom="16dp"
+        android:layout_marginBottom="20dp"
         android:layout_gravity="bottom|end"
         android:scaleType="centerCrop"
         />
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index 3c59b4e..fdfefe1 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -39,7 +39,7 @@
         <com.android.internal.widget.ImageFloatingTextView android:id="@+id/big_text"
             android:layout_width="match_parent"
             android:layout_height="0dp"
-            android:layout_marginTop="1dp"
+            android:layout_marginTop="0.5dp"
             android:paddingBottom="@dimen/notification_content_margin_bottom"
             android:textAppearance="@style/TextAppearance.Material.Notification"
             android:singleLine="false"
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index cda0636..809e525 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -24,7 +24,7 @@
     >
     <include layout="@layout/notification_template_header"
         android:layout_width="fill_parent"
-        android:layout_height="48dp" />
+        android:layout_height="53dp" />
     <LinearLayout
         android:id="@+id/notification_main_column"
         android:layout_width="match_parent"
@@ -54,7 +54,7 @@
             android:layout_height="match_parent"
             android:layout_gravity="bottom|end"
             android:layout_marginStart="10dp"
-            android:layout_marginBottom="8dp"
+            android:layout_marginBottom="12dp"
             android:layoutDirection="ltr"
             android:orientation="horizontal"
             >
diff --git a/core/res/res/layout/notification_template_right_icon.xml b/core/res/res/layout/notification_template_right_icon.xml
index 3b358ab..15ccc67 100644
--- a/core/res/res/layout/notification_template_right_icon.xml
+++ b/core/res/res/layout/notification_template_right_icon.xml
@@ -19,7 +19,7 @@
     android:layout_width="40dp"
     android:layout_height="40dp"
     android:layout_marginEnd="16dp"
-    android:layout_marginTop="32dp"
+    android:layout_marginTop="36dp"
     android:layout_gravity="top|end"
     android:scaleType="centerCrop"
     />
diff --git a/core/res/res/layout/notification_template_text.xml b/core/res/res/layout/notification_template_text.xml
index 47b30ec..a318bda 100644
--- a/core/res/res/layout/notification_template_text.xml
+++ b/core/res/res/layout/notification_template_text.xml
@@ -19,7 +19,7 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_gravity="top"
-    android:layout_marginTop="1dp"
+    android:layout_marginTop="0.5dp"
     android:ellipsize="marquee"
     android:fadingEdge="horizontal"
     android:gravity="top"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 666e1e7..dfdb6b0 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Kennisgewingluisteraar"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR-luisteraar"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Toestandverskaffer"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Kennisgewingklassifiseringsdiens"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN geaktiveer"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is geaktiveer deur <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Raak om die netwerk te bestuur."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Werkmodus is AF"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Stel werkprofiel in staat om te werk, insluitend programme, agtergrondsinkronisering en verwante kenmerke."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Skakel aan"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Deur %1$s gedeaktiveer"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Deur %1$s-administrateur gedeaktiveer. Kontak hulle om meer uit te vind."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Jy het nuwe boodskappe"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Maak SMS-program oop om te bekyk"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Sommige funksies kan beperk wees"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Ontspeld"</string>
     <string name="app_info" msgid="6856026610594615344">"Programinligting"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Raak om meer te wete te kom."</string>
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index e32562c..50f5f76 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ማሳወቂያ አዳማጭ"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"የምናባዊ እውነታ አዳማጭ"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"የሁኔታ አቅራቢ"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"የማሳወቂያ ደረጃ ሰጪ አገልግሎት"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ነቅቷል።"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN በ<xliff:g id="APP">%s</xliff:g>ገብሯል"</string>
     <string name="vpn_text" msgid="3011306607126450322">"አውታረመረብ ለማደራጀት  ንካ።"</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"የሥራ ሁነታ ጠፍቷል"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"መተግበሪያዎችን፣ የበስተጀርባ ሥምረት እና ተዛማጅ ባሕሪዎችን ጨምሮ የሥራ መገለጫ እንዲሰራ ይፍቀዱ።"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"አብራ"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ተሰናክሏል"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"በ%1$s አስተዳዳሪ ተሰናክሏል። የበለጠ ለመረዳት ያነጋግሯቸው።"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"አዲስ መልእክቶች አለዎት"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"ለመመልከት የኤስኤምኤስ መተግበሪያ ይክፈቱ"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"አንዳንድ ተግባሮች የተገደቡ ሊሆኑ ይችላሉ"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"ንቀል"</string>
     <string name="app_info" msgid="6856026610594615344">"የመተግበሪያ መረጃ"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"የበለጠ ለመረዳት ይንኩ።"</string>
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 06e0047..fcde691 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1169,8 +1169,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"برنامج تلقّي الإشعارات الصوتية"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"مستمع واقع افتراضي"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"موفر الحالة"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"خدمة ترتيب أهمية الإشعارات"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏تم تنشيط الشبكة الظاهرية الخاصة (VPN)"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏تم تنشيط VPN بواسطة <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"المس لإدارة الشبكة."</string>
@@ -1626,8 +1625,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"وضع العمل معطَّل"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"السماح باستخدام الملف الشخصي للعمل، بما في ذلك التطبيقات ومزامنة الخلفية والميزات ذات الصلة."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"تشغيل"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"‏تم تعطيل %1$s"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"‏تم التعطيل بواسطة مشرف %1$s. يمكنك الاتصال به لمعرفة المزيد."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"لديك رسائل جديدة"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"‏فتح تطبيق الرسائل القصيرة SMS للعرض"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"ربما تكون بعض الوظائف مُقيّدة."</string>
@@ -1641,8 +1638,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"إزالة تثبيت"</string>
     <string name="app_info" msgid="6856026610594615344">"معلومات عن التطبيق"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"المس للتعرف على مزيد من المعلومات."</string>
 </resources>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index bd4d4b9..3bc0ec3 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -1051,12 +1051,12 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Əlavə seçimlər üçün toxunun."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB sazlama qoşuludur"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB debaqı deaktivasiya etmək üçün toxunun."</string>
-    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Baq hesabat verilir..."</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Baq hesabatı verilir..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Baq hesabatı paylaşılsın?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Baq hesabatı paylaşılır..."</string>
-    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"IT admininiz bu cihazda nasazlıqların aşkarlanması üçün baq hesabatı sorğusu göndərdi. Tətbiqlər və data paylaşıla bilər."</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"İT admininiz bu cihazda nasazlıqların aşkarlanması üçün baq hesabatı sorğusu göndərdi. Tətbiqlər və data paylaşıla bilər."</string>
     <string name="share_remote_bugreport_action" msgid="6249476773913384948">"PAYLAŞIN"</string>
-    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RƏDD ET"</string>
+    <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RƏDD EDİN"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Klaviaturanı dəyişin"</string>
     <string name="configure_input_methods" msgid="4769971288371946846">"Klaviaturaları seçin"</string>
     <string name="show_ime" msgid="2506087537466597099">"Fiziki klaviatura aktiv olduğu halda ekranda saxlayın"</string>
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Bildiriş dinləyən"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR dinləyici"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Şərait provayderi"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Bildiriş qiymətləndirici xidmət"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktivləşdirildi"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN <xliff:g id="APP">%s</xliff:g> tərəfindən aktivləşdirilib"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Şəbəkəni idarə etmək üçün toxunun."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"İş rejimi DEAKTİVDİR"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Tətbiq, arxa fon sinxronizasiyası və digər əlaqədar xüsusiyyətlər daxil olmaqla iş profilinin fəaliyyətinə icazə verin."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivləşdirin"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s dekativ edildi"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s administratoru tərəfindən deaktiv edildi. Ətraflı məlumat üçün onlarla əlaqə saxlayın."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Yeni mesajlarınız var"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Baxmaq üçün SMS tətbiqini açın"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Bir neçə funksionallıq məhdudlaşdırıla bilər"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Çıxarın"</string>
     <string name="app_info" msgid="6856026610594615344">"Tətbiq məlumatı"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Daha çox məlumat üçün toxunun."</string>
 </resources>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 1fc8308..be40fa8 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1145,8 +1145,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Monitor obaveštenja"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Obrađivač za virtuelnu realnost"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Dobavljač uslova"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Usluga rangiranja obaveštenja"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN je aktiviran"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikacija <xliff:g id="APP">%s</xliff:g> je aktivirala VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dodirnite da biste upravljali mrežom."</string>
@@ -1569,8 +1568,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Režim za Work je ISKLJUČEN"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Dozvoljava profilu za Work da funkcioniše, uključujući aplikacije, sinhronizaciju u pozadini i srodne funkcije."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Uključi"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Paket %1$s je onemogućen"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Onemogućio je administrator kompanije %1$s. Kontaktirajte ga da biste saznali više."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Imate nove poruke"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorite aplikaciju za SMS da biste pregledali"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Neke funkcije su možda ograničene"</string>
@@ -1584,8 +1581,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Otkači"</string>
     <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dodirnite da biste saznali više."</string>
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 0ac8829..40e9572 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1135,11 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Тапет"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промяна на тапета"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Слушател на известия"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Приемател за виртуална реалност"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Доставчик на условия"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Услуга за класифициране на известията"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN е активирана"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN е активирана от <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Докоснете за управление на мрежата."</string>
@@ -1551,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Работният режим е ИЗКЛЮЧЕН"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Разрешаване на функционирането на служебния потребителски профил, включително приложенията, синхронизирането на заден план и свързаните функции."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Включване"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Пакетът „%1$s“ е деактивиран"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Деактивирано от администратора на %1$s. Свържете се с него, за да научите повече."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Имате нови съобщения"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Преглед в приложението за SMS"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Някои функции може да са огранич."</string>
@@ -1566,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Освобождаване"</string>
     <string name="app_info" msgid="6856026610594615344">"Информация за приложението"</string>
     <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Докоснете, за да научите повече."</string>
 </resources>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 925a9d0..92bd3e7 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"বিজ্ঞপ্তির শ্রোতা"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR শ্রোতা"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"শর্ত প্রদানকারী"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"বিজ্ঞপ্তি র‌্যাঙ্কার পরিষেবা"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN সক্রিয়"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> এর দ্বারা VPN সক্রিয় করা হয়েছে"</string>
     <string name="vpn_text" msgid="3011306607126450322">"নেটওয়ার্ক পরিচালনা করতে স্পর্শ করুন৷"</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"কাজের মোড বন্ধ আছে"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"অ্যাপ্লিকেশান, পটভূমি সিঙ্ক এবং সম্পর্কিত বৈশিষ্ট্যগুলি সহ কর্মস্থলের প্রোফাইলটিকে কাজ করার মঞ্জুরি দিন।"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"চালু করুন"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s অক্ষম করা আছে"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s প্রশাসক অক্ষম করেছেন। আরো জানতে তাদের সাথে যোগাযোগ করুন।"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"আপনার নতুন বার্তা আছে"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"দেখার জন্য SMS অ্যাপ্লিকেশান খুলুন"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"কিছু ক্রিয়াকলাপ সীমিত হতে পারে"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"আনপিন করুন"</string>
     <string name="app_info" msgid="6856026610594615344">"অ্যাপ্লিকেশানের তথ্য"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"আরো জানতে স্পর্শ করুন৷"</string>
 </resources>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index eea3d58..ca7a80a 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -1145,8 +1145,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Usluga za praćenje obavještenja"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR slušalac"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Pružalac uslova"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Usluga rangiranja obavještenja"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviran"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikacija <xliff:g id="APP">%s</xliff:g> je aktivirala VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dodirnite za upravljanje mrežom."</string>
@@ -1569,8 +1568,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Radni način rada je ISKLJUČEN"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Omogući radnom profilu da funkcionira, uključujući aplikacije, sinhronizaciju u pozadini i povezane funkcije."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Uključi"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s – onemogućeno"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Onemogućio administrator (%1$s). Obratite mu se za više informacija."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Imate nove poruke"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorite SMS aplikaciju da biste pregledali poruke"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Neke funkcije mogu biti ograničene"</string>
@@ -1584,8 +1581,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Otkači"</string>
     <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dodirnite da saznate više."</string>
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 39346b8..a737412 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Oient de notificacions"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Processador de realitat virtual"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Proveïdor de condicions"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Servei de classificació de notificacions"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ha activat VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca per gestionar la xarxa."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Mode de feina desactivat"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Permet que el perfil professional funcioni, incloses les aplicacions, la sincronització en segon pla i les funcions relacionades."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Activa"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Aplicació %1$s desactivada"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"L\'administrador de l\'empresa %1$s ha desactivat el paquet. Contacta-hi per obtenir-ne més informació."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Tens missatges nous"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Obre l\'aplicació de SMS per veure\'ls"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Algunes funcions es limitaran"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"No fixis"</string>
     <string name="app_info" msgid="6856026610594615344">"Informació de l\'aplicació"</string>
     <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca per obtenir més informació."</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index f96dfa9..5b6a213 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1151,11 +1151,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Změnit tapetu"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Aplikace poslouchající oznámení"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Přijímač virtuální reality"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Poskytovatel podmínky"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Služba na hodnocení důležitosti oznámení"</string>
     <string name="vpn_title" msgid="19615213552042827">"Síť VPN je aktivována"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikace <xliff:g id="APP">%s</xliff:g> aktivovala síť VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotykem zobrazíte správu sítě."</string>
@@ -1589,8 +1587,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Pracovní režim je VYPNUTÝ"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Povolí fungování pracovního profilu, včetně aplikací, synchronizace na pozadí a souvisejících funkcí."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Zapnout"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Balíček %1$s byl zakázán"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Zakázáno administrátorem zařízení %1$s. Chcete-li získat další informace, kontaktujte jej."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Máte nové zprávy"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Zobrazíte je v aplikaci pro SMS"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Funkce mohou být omezeny"</string>
@@ -1604,8 +1600,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Odepnout"</string>
     <string name="app_info" msgid="6856026610594615344">"Informace o aplikaci"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Klepnutím zobrazíte další informace."</string>
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 47ca429..06861e7 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1135,11 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Baggrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Skift baggrund"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Underretningslytter"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR-lyttefunktion"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Tjeneste til formidling af betingelser"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Tjeneste til rangering af underretninger"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN er aktiveret."</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveres af <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tryk for at administrere netværket."</string>
@@ -1551,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Arbejdstilstand er slået FRA"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Tillad, at arbejdsprofilen aktiveres, bl.a. i forbindelse med apps, baggrundssynkronisering og relaterede funktioner."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Slå til"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s er deaktiveret"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Deaktiveret af %1$s administrator. Kontakt vedkommende for at få flere oplysninger."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Du har nye beskeder"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Åbn sms-appen for at se beskeden"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Nogle funktioner er begrænsede"</string>
@@ -1566,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Frigør"</string>
     <string name="app_info" msgid="6856026610594615344">"Oplysninger om appen"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tryk for at få flere oplysninger."</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index d04d6b6..30188b5 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1051,7 +1051,7 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Für weitere Optionen tippen"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB-Debugging"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"Zum Deaktivieren berühren"</string>
-    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Fehlerbericht wird aufgerufen…"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Fehlerbericht wird abgerufen…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Fehlerbericht teilen?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Fehlerbericht wird geteilt…"</string>
     <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"Dein IT-Administrator hat einen Fehlerbericht zur Fehlerbehebung für dieses Gerät angefordert. Apps und Daten werden unter Umständen geteilt."</string>
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Benachrichtigungs-Listener"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR-Listener"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Bedingungsprovider"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Service für Einstufung von Benachrichtigungen"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviert"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN wurde von <xliff:g id="APP">%s</xliff:g> aktiviert."</string>
     <string name="vpn_text" msgid="3011306607126450322">"Zum Verwalten des Netzwerks berühren"</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Arbeitsmodus ist AUS"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Arbeitsprofil aktivieren, einschließlich Apps, Synchronisierung im Hintergrund und verknüpfter Funktionen."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivieren"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s deaktiviert"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Durch den Administrator von %1$s deaktiviert. Setze dich für weitere Informationen mit ihm in Verbindung."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Du hast neue Nachrichten"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Zum Ansehen SMS-App öffnen"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Einige Funktionen sind evtl. eingeschränkt"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Markierung entfernen"</string>
     <string name="app_info" msgid="6856026610594615344">"App-Informationen"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Für weitere Informationen tippen."</string>
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index b39d8d8..1091495 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Υπηρεσία ακρόασης ειδοποίησης"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Λειτουργία ακρόασης Εικονικής Πραγματικότητας"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Πάροχος συνθηκών"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Υπηρεσία κατάταξης ειδοποιήσεων"</string>
     <string name="vpn_title" msgid="19615213552042827">"Το VPN ενεργοποιήθηκε"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Το VPN ενεργοποιήθηκε από την εφαρμογή <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Αγγίξτε για τη διαχείριση του δικτύου."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Λειτουργία εργασίας ΑΠΕΝΕΡΓ/ΝΗ"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Να επιτρέπεται η λειτουργία του προφίλ εργασίας σας, συμπεριλαμβανομένων των εφαρμογών, του συγχρονισμού στο παρασκήνιο και των σχετικών λειτουργιών."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Ενεργοποίηση"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Το %1$s απενεργοποιήθηκε"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Απενεργοποιήθηκε από το διαχειριστή της συσκευής %1$s. Επικοινωνήστε με το διαχειριστή για να μάθετε περισσότερα."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Έχετε νέα μηνύματα"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Άνοιγμα της εφαρμογής SMS για προβολή"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Μερ. λειτ. ίσως είναι περιορ."</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Ξεκαρφίτσωμα"</string>
     <string name="app_info" msgid="6856026610594615344">"Πληροφορίες εφαρμογής"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Αγγίξτε για να μάθετε περισσότερα."</string>
 </resources>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 21c502e..58d45ba 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR listener"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Condition provider"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Notification ranker service"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activated"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Touch to manage the network."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Work mode is OFF"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Allow work profile to function, including apps, background sync and related features."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Turn on"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s disabled"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Disabled by %1$s administrator. Contact them to find out more."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"You have new messages"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Open SMS app to view"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Some functionality may be limited"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
     <string name="app_info" msgid="6856026610594615344">"App info"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 21c502e..58d45ba 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR listener"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Condition provider"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Notification ranker service"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activated"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Touch to manage the network."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Work mode is OFF"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Allow work profile to function, including apps, background sync and related features."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Turn on"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s disabled"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Disabled by %1$s administrator. Contact them to find out more."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"You have new messages"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Open SMS app to view"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Some functionality may be limited"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
     <string name="app_info" msgid="6856026610594615344">"App info"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string>
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 21c502e..58d45ba 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR listener"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Condition provider"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Notification ranker service"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activated"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Touch to manage the network."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Work mode is OFF"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Allow work profile to function, including apps, background sync and related features."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Turn on"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s disabled"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Disabled by %1$s administrator. Contact them to find out more."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"You have new messages"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Open SMS app to view"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Some functionality may be limited"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
     <string name="app_info" msgid="6856026610594615344">"App info"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index c84970f..225116f 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Agente de escucha de notificaciones"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Procesador de realidad virtual"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Proveedor de condiciones"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Servicio de clasificación de notificaciones"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN está activado por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca para administrar la red."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabajo DESACTIVADO"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Permite que se active el perfil de trabajo, incluidas las apps, la sincronización en segundo plano y las funciones relacionadas."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Activar"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Se inhabilitó %1$s"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"El administrador de %1$s lo inhabilitó. Comunícate con él para obtener más información."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Tienes mensajes nuevos"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Abrir app de SMS para ver el mensaje"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Funciones limitadas"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"No fijar"</string>
     <string name="app_info" msgid="6856026610594615344">"Información de la app"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para obtener más información."</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 3e220fe..5ce1711 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -909,8 +909,8 @@
     <string name="noApplications" msgid="2991814273936504689">"Ninguna aplicación puede realizar esta acción."</string>
     <string name="aerr_application" msgid="250320989337856518">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> ha dejado de funcionar"</string>
     <string name="aerr_process" msgid="6201597323218674729">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> ha dejado de funcionar"</string>
-    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> sigue dejando de funcionar"</string>
-    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> sigue dejando de funcionar"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> sigue sin funcionar"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> sigue sin funcionar"</string>
     <string name="aerr_restart" msgid="9001379185665886595">"Reiniciar aplicación"</string>
     <string name="aerr_reset" msgid="7645427603514220451">"Restablecer y reiniciar aplicación"</string>
     <string name="aerr_report" msgid="5371800241488400617">"Enviar sugerencias"</string>
@@ -1135,10 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fondo de pantalla"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Detector de notificaciones"</string>
-    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Procesador de Realidad Virtual"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Procesador de RV"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Proveedor de condiciones"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Servicio de clasificación de notificaciones"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activada por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca para administrar la red."</string>
@@ -1447,7 +1446,7 @@
       <item quantity="one">Vuelve a intentarlo en 1 segundo</item>
     </plurals>
     <string name="restr_pin_try_later" msgid="973144472490532377">"Volver a intentar más tarde"</string>
-    <string name="immersive_cling_title" msgid="8394201622932303336">"Mostrando pantalla completa"</string>
+    <string name="immersive_cling_title" msgid="8394201622932303336">"Modo de pantalla completa"</string>
     <string name="immersive_cling_description" msgid="3482371193207536040">"Para salir, desliza hacia abajo desde arriba."</string>
     <string name="immersive_cling_positive" msgid="5016839404568297683">"Entendido"</string>
     <string name="done_label" msgid="2093726099505892398">"Listo"</string>
@@ -1550,12 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabajo desactivado"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Permite que se utilice el perfil de trabajo, incluidas las aplicaciones, la sincronización en segundo plano y las funciones relacionadas."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Activar"</string>
-    <!-- String.format failed for translation -->
-    <!-- no translation found for suspended_package_title (3408150347778524435) -->
-    <skip />
-    <!-- String.format failed for translation -->
-    <!-- no translation found for suspended_package_message (6341091587106868601) -->
-    <skip />
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Tienes mensajes nuevos"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Abre la aplicación de SMS para ver el mensaje"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Algunas funciones limitadas"</string>
@@ -1569,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"No fijar"</string>
     <string name="app_info" msgid="6856026610594615344">"Información de la aplicación"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para obtener más información."</string>
 </resources>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index dd08800..3ce50d9 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Märguannete kuulamisteenus"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Virtuaalreaalses režiimis kuulaja"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Tingimuse pakkuja"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Märguannete tähtsuse määramise teenus"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN on aktiveeritud"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-i aktiveeris <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Võrgu haldamiseks puudutage."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Töörežiim on VÄLJA LÜLITATUD"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Lubatakse tööprofiili toimingud, sh rakendused, taustal sünkroonimine ja seotud funktsioonid."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Lülita sisse"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Üksus %1$s on keelatud"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Keelas seadme %1$s administraator. Lisateabe saamiseks võtke temaga ühendust."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Teile on uusi sõnumeid"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Avage vaatamiseks SMS-rakendus"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Funktsioon võib olla piiratud"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Vabasta"</string>
     <string name="app_info" msgid="6856026610594615344">"Rakenduse teave"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Lisateabe saamiseks puudutage."</string>
 </resources>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 1811edb..6c41c2c 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Jakinarazpenak hautemateko zerbitzua"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Errealitate birtualeko hautemailea"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Baldintza-hornitzailea"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Jakinarazpenen sailkapen-zerbitzua"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN eginbidea aktibatuta"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> aplikazioak VPN konexioa aktibatu du"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Ukitu sarea kudeatzeko."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Desaktibatuta dago laneko modua"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Baimendu laneko profilak funtzionatzea, besteak beste, aplikazioak, atzeko planoko sinkronizazioa eta erlazionatutako eginbideak."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktibatu"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Desgaituta dago %1$s"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Desgaitu egin du %1$s gailuaren administratzaileak. Informazio gehiago lortu nahi baduzu, jarri harekin harremanetan."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Mezu berriak dituzu"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Mezuak ikusteko, ireki SMS mezuen aplikazioa"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Funtzioak mugatuta egon litezke"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Kendu aingura"</string>
     <string name="app_info" msgid="6856026610594615344">"Aplikazioari buruzko informazioa"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Sakatu informazio gehiago lortzeko."</string>
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 4e801cc..aba5e08 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"شنونده اعلان"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"‏شنونده VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ارائه‌دهنده وضعیت"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"سرویس رتبه‌بندی اعلان"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏VPN فعال شد"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏VPN توسط <xliff:g id="APP">%s</xliff:g> فعال شده است"</string>
     <string name="vpn_text" msgid="3011306607126450322">"برای مدیریت شبکه لمس کنید."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"حالت کاری خاموش است"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"به نمایه کاری اجازه فعالیت ( شامل استفاده از برنامه‌ها، همگام‌سازی در پس‌زمینه و قابلیت‌های مرتبط) داده شود."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"روشن کردن"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"‏%1$s غیرفعال است"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"‏سرپرست %1$s آن را غیرفعال کرده است. برای اطلاعات بیشتر با او تماس بگیرید."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"پیام‌های جدیدی دارید"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"برای مشاهده، برنامه پیامک را باز کنید"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"ممکن است برخی از عملکردها محدود باشند"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"برداشتن پین"</string>
     <string name="app_info" msgid="6856026610594615344">"اطلاعات برنامه"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"برای یادگیری بیشتر لمس کنید."</string>
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 300328b..e52d870 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Ilmoituskuuntelija"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Virtuaalitodellisuuden kuuntelija"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Ehtojen toimituspalvelu"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Ilmoitusten sijoituspalvelu"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN on aktivoitu"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> on aktivoinut VPN-yhteyden"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Voit hallinnoida verkkoa koskettamalla."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Työtila on pois käytöstä"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Sallii työprofiiliin toiminnan, esimerkiksi sovellukset ja taustasynkronoinnin."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Ota käyttöön"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s poisti tämän käytöstä"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Organisaation %1$s järjestelmänvalvojan käytöstä poistama. Kysy häneltä lisätietoja."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Sinulle on uusia viestejä"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Katso avaamalla tekstiviestisovellus."</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Toimintorajoitus mahdollinen"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Irrota"</string>
     <string name="app_info" msgid="6856026610594615344">"Sovelluksen tiedot"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Lue lisätietoja koskettamalla."</string>
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 6688060..acfd0a6 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Outil d\'écoute des notifications"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Écouteur de réalité virtuelle"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Fournisseur de conditions"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Service de classement des notifications"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activé"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activé par <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Appuyez ici pour gérer le réseau."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Le mode Travail est désactivé"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Autoriser le fonctionnement du profil professionnel, y compris les applications, la synchronisation en arrière-plan et les fonctionnalités associées."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Activer"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s est désactivé"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Cette option a été désactivée par l\'administrateur de %1$s. Communiquez avec lui pour en savoir plus."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Vous avez de nouveaux messages"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Ouvrez l\'application de messagerie texte pour l\'afficher"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Certaines fonct. sont limitées"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Annuler l\'épinglage"</string>
     <string name="app_info" msgid="6856026610594615344">"Détails de l\'application"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touchez ici pour en savoir plus."</string>
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 097a8a1..d3bb5d0 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Outil d\'écoute des notifications"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Écouteur de réalité virtuelle"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Fournisseur de conditions"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Service de classement des notifications"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activé"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activé par <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Appuyez ici pour gérer le réseau."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Mode professionnel DÉSACTIVÉ"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Autoriser le fonctionnement du profil professionnel, y compris les applications, la synchronisation en arrière-plan et les fonctionnalités associées."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Activer"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s désactivé"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Désactivé par l\'administrateur %1$s. Contactez-le pour en savoir plus."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Vous avez de nouveaux messages"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Ouvrir l\'application de SMS pour afficher le message"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Des fonctionnalités peuvent être limitées"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Retirer"</string>
     <string name="app_info" msgid="6856026610594615344">"Infos sur l\'appli"</string>
     <string name="negative_duration" msgid="5688706061127375131">"− <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Appuyez ici pour en savoir plus."</string>
 </resources>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index fb98b76c..6a2b7f3 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Axente de escoita de notificacións"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Axente de escoita de RV"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provedor de condicións"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Servizo de clasificación de notificacións"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> activou a VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca aquí para xestionar a rede."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de traballo DESACTIVADO"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Permite que funcione o perfil de traballo, incluídas as aplicacións, a sincronización en segundo plano e as funcións relacionadas."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Activar"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Desactivouse %1$s"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"O administrador de %1$s desactivou este paquete. Contacta con el para obter máis información."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Tes mensaxes novas"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Abre a aplicación de SMS para ver as mensaxes"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Pode haber funcións limitadas"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Soltar"</string>
     <string name="app_info" msgid="6856026610594615344">"Información da aplicación"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para acceder a máis información"</string>
 </resources>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 1fa64bc..7595a88 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"સૂચના સાંભળનાર"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR સાંભળનાર"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"શરત પ્રદાતા"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"સૂચના રેંકર સેવા"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN સક્રિય કર્યું"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> દ્વારા VPN સક્રિય થયું"</string>
     <string name="vpn_text" msgid="3011306607126450322">"નેટવર્કને સંચાલિત કરવા માટે ટચ કરો."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"કાર્ય મોડ બંધ છે"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"કાર્ય પ્રોફાઇલને ઍપ્લિકેશનો, પૃષ્ઠભૂમિ સમન્વયન અને સંબંધિત સુવિધાઓ સહિતનું કાર્ય કરવાની મંજૂરી આપો."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"ચાલુ કરો"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s અક્ષમ કરેલ"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ. વધુ જાણવા માટે તેમનો સંપર્ક કરો."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"તમારી પાસે નવા સંદેશા છે"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"જોવા માટે SMS ઍપ્લિકેશન ખોલો"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"કેટલીક કાર્યક્ષમતા મર્યાદિત હોઈ શકે છે"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"અનપિન કરો"</string>
     <string name="app_info" msgid="6856026610594615344">"ઍપ્લિકેશન માહિતી"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"વધુ જાણવા માટે ટચ કરો."</string>
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index fbd50ed..3c33b38 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"नोटिफिकेशन श्रवणकर्ता"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR श्रोता"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"स्थिति प्रदाता"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"नोटिफ़िकेशन रैंकर सेवा"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN सक्रिय"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN को <xliff:g id="APP">%s</xliff:g> द्वारा सक्रिय किया गया है"</string>
     <string name="vpn_text" msgid="3011306607126450322">"नेटवर्क प्रबंधित करने के लिए स्‍पर्श करें."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"कार्य मोड बंद है"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"ऐप्स, पृष्ठभूमि समन्वयन और संबंधित सुविधाओं सहित कार्य प्रोफ़ाइल को काम करने की अनुमति दें"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"चालू करें"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s को अक्षम किया गया"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s व्‍यवस्‍थापक द्वारा अक्षम किया गया. अधिक जानने के लिए उनसे संपर्क करें."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"आपके पास नए संदेश हैं"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"देखने के लिए SMS ऐप खोलें"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"कुछ कार्य क्षमताएं सीमित हो सकती हैं"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"अनपिन करें"</string>
     <string name="app_info" msgid="6856026610594615344">"ऐप की जानकारी"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"अधिक जानने के लिए स्पर्श करें."</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index d396c07..862ee60 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1145,8 +1145,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Slušatelj obavijesti"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Slušatelj virtualne stvarnosti"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Davatalj uvjeta"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Usluga rangiranja obavijesti"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviran"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikacija <xliff:g id="APP">%s</xliff:g> aktivirala je VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dodirnite za upravljanje mrežom."</string>
@@ -1569,8 +1568,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Radni je način ISKLJUČEN"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Omogućuje radnom profilu da funkcionira, uključujući aplikacije, sinkronizaciju u pozadini i povezane značajke."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Uključi"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s – onemogućeno"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Onemogućio administrator (%1$s). Obratite mu se za više informacija."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Imate nove poruke"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorite SMS aplikaciju da biste pregledali poruke"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Funkcije mogu biti ograničene"</string>
@@ -1584,8 +1581,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Otkvači"</string>
     <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dodirnite da biste saznali više."</string>
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 987d1f9..d6114fa 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Értesítésfigyelő"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Virtuálisvalóság-figyelő"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Feltételbiztosító"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Értesítésrangsoroló szolgáltatás"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiválva"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A(z) <xliff:g id="APP">%s</xliff:g> aktiválta a VPN-t"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Érintse meg a hálózat kezeléséhez."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"A munka mód KI van kapcsolva"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Munkaprofil használatának engedélyezése, beleértve az alkalmazásokat, a háttérben való szinkronizálást és a kapcsolódó funkciókat."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Bekapcsolás"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s letiltva"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"A(z) %1$s szervezet rendszergazdája letiltotta. További információért vegye fel vele a kapcsolatot."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Új üzenetei érkeztek"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"SMS-alkalmazás megnyitása a megtekintéshez"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Egyes funkciók korlátozva lehetnek"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Feloldás"</string>
     <string name="app_info" msgid="6856026610594615344">"Alkalmazásinformáció"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Érintse meg a további információkért."</string>
 </resources>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index f02b9dd..0b2fe57 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1135,11 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Պաստառ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Փոխել պաստառը"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Ծանուցման ունկնդիր"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR ունկնդրիչ"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Պայմանների մատակարար"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Ծանուցումների դասակարգման ծառայություն"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN-ը ակտիվացված է"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-ն ակտիվացված է <xliff:g id="APP">%s</xliff:g>-ի կողմից"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Հպեք` ցանցի կառավարման համար:"</string>
@@ -1551,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Աշխատանքային ռեժիմն ԱՆՋԱՏՎԱԾ Է"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Թույլատրել աշխատանքային պրոֆիլի (այդ թվում նաև հավելվածների, ֆոնային համաժամացման և առնչվող գործառական հնարավորությունների) աշխատանքը:"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Միացնել"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s-ը կասեցվել է"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Կասեցվել է %1$s ադմինիստրատորի կողմից: Ավելին իմանալու համար կապվեք նրա հետ:"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Դուք ունեք նոր հաղորդագրություններ"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Դիտելու համար բացել SMS հավելվածը"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Որոշ գործառույթներ կարող են սահմանափակված լինել"</string>
@@ -1566,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Ապամրացնել"</string>
     <string name="app_info" msgid="6856026610594615344">"Հավելվածի տվյալներ"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Հպեք՝ ավելին իմանալու համար:"</string>
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 8c0da19..fca667a 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Pendengar pemberitahuan"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Pemroses Realitas Maya"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Penyedia ketentuan"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Layanan penentu peringkat notifikasi"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN diaktifkan"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Sentuh untuk mengelola jaringan."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Mode kerja NONAKTIF"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Izinkan profil kerja berfungsi, termasuk aplikasi, sinkronisasi latar belakang, dan fitur terkait."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktifkan"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s dinonaktifkan"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Dinonaktifkan oleh administrator %1$s. Hubungi administrator untuk mempelajari lebih lanjut."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Ada pesan baru"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Buka aplikasi SMS untuk melihat"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Beberapa fungsi mungkin terbatas"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Lepas pin"</string>
     <string name="app_info" msgid="6856026610594615344">"Info aplikasi"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Sentuh untuk mempelajari lebih lanjut."</string>
 </resources>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index b58dc05..dc41214 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Tilkynningahlustun"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Sýndarveruleikavöktun"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Skilyrðaveita"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Tilkynningaröðun"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN virkjað"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN er virkjað með <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Snertu til að hafa umsjón með netinu."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Slökkt á vinnusniði"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Leyfa virkni vinnusniðs, m.a. forrita, samstillingar í bakgrunni og tengdra eiginleika."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Kveikja"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s óvirkt"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Gert óvirkt af stjórnanda %1$s. Hafðu samband við hann til að fá frekari upplýsingar."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Þú ert með ný skilaboð"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Opnaðu SMS-forritið til að skoða"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Sum virkni kann að vera takmörkuð"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Losa"</string>
     <string name="app_info" msgid="6856026610594615344">"Forritsupplýsingar"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Snertu til að fá frekari upplýsingar."</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 41ba923..c43470b 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Listener di notifica"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Listener realtà virtuale"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provider condizioni"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Servizio di classificazione delle notifiche"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN attiva"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN attivata da <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tocca per gestire la rete."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Modalità Lavoro DISATTIVATA"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Attiva il profilo di lavoro, incluse app, sincronizzazione in background e funzioni correlate."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Attiva"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s disattivato"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Disattivato dall\'amministratore di %1$s. Contattalo per ulteriori informazioni."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Hai nuovi messaggi"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Apri l\'app SMS per la visualizzazione"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Funzioni potenzial. limitate"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Sblocca"</string>
     <string name="app_info" msgid="6856026610594615344">"Informazioni app"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tocca per ulteriori informazioni."</string>
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 226b390..246140b 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1151,11 +1151,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"טפט"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"שנה טפט"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"מאזין להתראות"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"‏VR ליסנר"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ספק תנאי"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"שירות של דירוג הודעות"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏VPN מופעל"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏VPN מופעל על ידי <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"גע כדי לנהל את הרשת."</string>
@@ -1589,8 +1587,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"מצב העבודה כבוי"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"אפשר לפרופיל העבודה לפעול, כולל אפליקציות, סנכרון ברקע ותכונות קשורות."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"הפעל"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"‏החבילה %1$s הושבתה"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"‏הושבתה על ידי מנהל המערכת של %1$s. צור איתו קשר כדי לקבל מידע נוסף."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"יש לך הודעות חדשות"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"‏פתח את אפליקציית ה-SMS כדי להציג"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"ייתכן שחלק מהפונקציונליות תהיה מוגבלת"</string>
@@ -1604,8 +1600,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"בטל הצמדה"</string>
     <string name="app_info" msgid="6856026610594615344">"פרטי אפליקציה"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"גע לקבלת מידע נוסף."</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index b494851..1cd079b 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知リスナー"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR リスナー"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"コンディションプロバイダ"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"通知ランカー サービス"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPNが有効になりました"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPNが<xliff:g id="APP">%s</xliff:g>により有効化されました"</string>
     <string name="vpn_text" msgid="3011306607126450322">"タップしてネットワークを管理します。"</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Work モード OFF"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"仕事用プロファイルで、アプリ、バックグラウンド同期などの関連機能の使用を許可します。"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"ON にする"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$sが無効です"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s管理者によって無効になっています。詳しくは管理者までお問い合わせください。"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"新着メッセージがあります"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"表示するには SMS アプリを開きます"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"一部機能が制限されている可能性"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"固定を解除"</string>
     <string name="app_info" msgid="6856026610594615344">"アプリ情報"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"タップして詳細をご確認ください。"</string>
 </resources>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index ecef3da..8ff6a09 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1135,11 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ფონი"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ფონის შეცვლა"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"შეტყობინებების მსმენელი"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"ვირტუალური რეალობის მსმენელი"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"მდგომარეობის პროვაიდერი"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"შეტყობინებების მნიშვნელობის დონის შეფასების სერვისი"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN გააქტიურებულია"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN გააქტიურებულია <xliff:g id="APP">%s</xliff:g>-ის მიერ"</string>
     <string name="vpn_text" msgid="3011306607126450322">"შეეხეთ ქსელის სამართავად."</string>
@@ -1551,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"სამსახურის რეჟიმი გამორთულია"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"სამსახურის პროფილის მუშაობის დაშვება, მათ შორის, აპების, ფონური სინქრონიზაციის და დაკავშირებული ფუნქციების."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"ჩართვა"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s გათიშულია"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"გათიშულია „%1$s“-ის ადმინისტრატორის მიერ. დაუკავშირდით მას მეტის გასაგებად."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"თქვენ ახალი შეტყობინებები გაქვთ"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"სანახავად, გახსენით SMS აპი"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"ზოგიერთი ფუნქცია შეიძლება შეიზღუდოს"</string>
@@ -1566,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"ჩამაგრების მოხსნა"</string>
     <string name="app_info" msgid="6856026610594615344">"აპის შესახებ"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"შეეხეთ მეტის გასაგებად."</string>
 </resources>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 8f5a667..a0e987d 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1051,10 +1051,10 @@
     <string name="usb_notification_message" msgid="7347368030849048437">"Қосымша параметрлер үшін түртіңіз."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB жөндеу қосылған"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"USB жөндеуді өшіру үшін түртіңіз."</string>
-    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Қате туралы есеп құрылуда…"</string>
+    <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Қате туралы есеп алынуда…"</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Қате туралы есепті бөлісу керек пе?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Қате туралы есеп бөлісілуде…"</string>
-    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"АТ әкімшісі осы құрылғы ақауларын жоюға көмектесу үшін қате туралы есепті сұрады. Қолданбалар және деректер бөлісілуі мүмкін."</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"АТ әкімшісі осы құрылғы ақауларын жоюға көмектесу үшін қате туралы есепті сұрады. Оған қолданбалар мен деректер көрсетілуі мүмкін."</string>
     <string name="share_remote_bugreport_action" msgid="6249476773913384948">"БӨЛІСУ"</string>
     <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ҚАБЫЛДАМАУ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"Пернетақтаны өзгерту"</string>
@@ -1135,10 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Артқы фоны"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Артқы фонын өзгерту"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Хабар бақылағыш"</string>
-    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR тыңдаушы"</string>
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Виртуалды шынайылық тыңдаушысы"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Шарт провайдері"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Хабарландыруларды жіктеу қызметі"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN белсенді"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"ВЖЭ <xliff:g id="APP">%s</xliff:g> арқылы қосылған"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Желіні басқару үшін түрту."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Жұмыс режимі ӨШІРУЛІ"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Жұмыс профиліне, соның ішінде, қолданбаларға, фондық синхрондауға және қатысты мүмкіндіктерге жұмыс істеуге рұқсат ету."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Қосу"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s өшірілген"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s әкімшісі өшірген. Қосымша мәліметтер алу үшін оларға хабарласыңыз."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Сізде жаңа хабарлар бар"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Көру үшін SMS қолданбасын ашыңыз"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Кейбір функциялар істемеуі мүмкін"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Босату"</string>
     <string name="app_info" msgid="6856026610594615344">"Қолданба ақпараты"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Қосымша мәліметтер алу үшін түртіңіз."</string>
 </resources>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 0c69f930..e586c78 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1137,11 +1137,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ផ្ទាំង​រូបភាព"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ប្ដូរ​ផ្ទាំង​រូបភាព"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"កម្មវិធី​ស្ដាប់​ការ​ជូន​ដំណឹង"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"កម្មវិធីស្តាប់ VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ក្រុមហ៊ុន​ផ្ដល់​លក្ខខណ្ឌ"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"សេវាកម្មវាយតម្លៃការជូនដំណឹង"</string>
     <string name="vpn_title" msgid="19615213552042827">"បាន​ធ្វើ​ឲ្យ VPN សកម្ម"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"បាន​ធ្វើ​ឲ្យ VPN សកម្ម​ដោយ <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ប៉ះ ដើម្បី​គ្រប់គ្រង​បណ្ដាញ។"</string>
@@ -1553,8 +1551,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"របៀបការងារបានបិទ"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"អនុញ្ញាតឲ្យប្រវត្តិរូបការងារដំណើរការ ដោយរាប់បញ្ចូលទាំងកម្មវិធី ការធ្វើសមកាលកម្មផ្ទៃខាងក្រោយ និងលក្ខណៈពិសេសដែលពាក់ព័ន្ធ។"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"បើក"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"បានបិទដំណើរការ %1$s"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"បិទដំណើរការដោយអ្នកគ្រប់គ្រង %1$s។ សូមទាក់ទងពួកគេដើម្បីស្វែងយល់បន្ថែម។"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"អ្នកមានសារថ្មី"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"បើកកម្មវិធីសារ SMS ដើម្បីមើល"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"លទ្ធភាពប្រើមុខងារមួយចំនួនអាចត្រូវបាកម្រិត"</string>
@@ -1568,8 +1564,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"មិនខ្ទាស់"</string>
     <string name="app_info" msgid="6856026610594615344">"ព័ត៌មាន​កម្មវិធី"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ប៉ះ​ ដើម្បី​​ស្វែងយល់​បន្ថែម។"</string>
 </resources>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index af44c83..74aa801 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ಅಧಿಸೂಚನೆ ಕೇಳುಗ"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR ಕೇಳುವಿಕೆ"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ಕಂಡೀಶನ್ ಪೂರೈಕೆದಾರರು"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"ಅಧಿಸೂಚನೆ ಶ್ರೇಣಿಯ ಸೇವೆ"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ಮೂಲಕ VPN ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ನೆಟ್‍ವರ್ಕ್ ನಿರ್ವಹಿಸಲು ಸ್ಪರ್ಶಿಸಿ"</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"ಕೆಲಸದ ಮೋಡ್ ಆಫ್ ಆಗಿದೆ"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಹಿನ್ನೆಲೆ ಸಿಂಕ್ ಮತ್ತು ಇತರ ಸಂಬಂಧಿತ ವೈಶಿಷ್ಟ್ಯಗಳು ಸೇರಿದಂತೆ ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್‌‌ ಕಾರ್ಯನಿರ್ವಹಿಸಲು ಅನುಮತಿಸಿ."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"ಆನ್ ಮಾಡು"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s ನಿರ್ವಾಹಕರಿಂದ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ. ಇನ್ನಷ್ಟು ತಿಳಿದುಕೊಳ್ಳಲು ಅವರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"ನೀವು ಹೊಸ ಸಂದೇಶಗಳನ್ನು ಹೊಂದಿರುವಿರಿ"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"ವೀಕ್ಷಿಸಲು SMS ಅಪ್ಲಿಕೇಶನ್ ತೆರೆಯಿರಿ"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"ಕೆಲವು ಕಾರ್ಯನಿರ್ವಹಣೆಗಳು ಸೀಮಿತವಾಗಿರಬಹುದು"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"ಅನ್‌ಪಿನ್"</string>
     <string name="app_info" msgid="6856026610594615344">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಸ್ಪರ್ಶಿಸಿ."</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 0109279..3c09cfb 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1135,11 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"배경화면"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"배경화면 변경"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"알림 수신기"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"가상 현실 리스너"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"조건 제공자"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"알림 순위 지정 서비스"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN이 활성화됨"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN이 <xliff:g id="APP">%s</xliff:g>에 의해 활성화됨"</string>
     <string name="vpn_text" msgid="3011306607126450322">"네트워크를 관리하려면 터치하세요."</string>
@@ -1551,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"직장 모드가 사용 중지됨"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"앱, 백그라운드 동기화 및 관련 기능을 포함한 직장 프로필이 작동하도록 허용"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"사용 설정"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s이(가) 사용 중지됨"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s 관리자에 의해 사용 중지되었습니다. 자세히 알아보려면 관리자에게 문의하세요."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"새 메시지 있음"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"SMS 앱을 열고 확인"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"일부 기능이 제한될 수 있습니다."</string>
@@ -1566,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"고정 해제"</string>
     <string name="app_info" msgid="6856026610594615344">"앱 정보"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"자세한 내용을 보려면 터치하세요."</string>
 </resources>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 09317323..d10a50f 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1136,11 +1136,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Тушкагаз"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Тушкагазды өзгөртүү"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Эскертүү тыңшагычы"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR режими"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Шарт түзүүчү"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Эскертмелердин маанилүүлүгүн баалоо кызматы"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN иштетилди"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN <xliff:g id="APP">%s</xliff:g> аркылуу жандырылды"</string>
     <string name="vpn_text" msgid="3011306607126450322">"желени башкаруу үчүн басыңыз."</string>
@@ -1552,8 +1550,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Жумуш режими ӨЧҮРҮЛГӨН"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Жумуш профилин, ошондой эле колдонмолорду, фондо шайкештирүү жана ага байланыштуу функцияларды иштетиңиз."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Күйгүзүү"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s өчүрүлгөн"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s администратору тарабынан өчүрүлгөн. Көбүрөөк билүү үчүн администраторго кайрылыңыз."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Сизге жаңы билдирүүлөр келди"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Көрүү үчүн SMS колдонмосун ачыңыз"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Айрым функциялар чектлши мүмкн"</string>
@@ -1567,8 +1563,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Кадоодон алып коюу"</string>
     <string name="app_info" msgid="6856026610594615344">"Колдонмо тууралуу"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Көбүрөөк билүү үчүн тийип коюңуз."</string>
 </resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 2d680a9..46cc85a 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ໂຕຟັງການແຈ້ງເຕືອນ"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"ຕົວຟັງ VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"​ຜູ່​ສະ​ໜອງ​ເງື່ອນ​ໄຂ"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"ບໍລິການຈັດອັນດັບການແຈ້ງເຕືອນ"</string>
     <string name="vpn_title" msgid="19615213552042827">"ເປີດນຳໃຊ້ VPN ແລ້ວ"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"ເປີດໃຊ້ VPN ໂດຍ <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ແຕະເພື່ອຈັດການເຄືອຂ່າຍ."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"ໂໝດບ່ອນເຮັດວຽກປິດຢູ່"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"ອະນຸຍາດໃຫ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກສາມາດນຳໃຊ້ໄດ້ ເຊິ່ງຮວມທັງແອັບ, ການຊິ້ງຂໍ້ມູນໃນພື້ນຫຼັງ ແລະ ຄຸນສົມບັດທີ່ກ່ຽວຂ້ອງ."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"ເປີດ​"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ຖືກປິດໃຊ້ແລ້ວ"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"ຖືກປິດໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບ %1$s. ກະລຸນາຕິດຕໍ່ຫາພວກເຂົາເພື່ອສຶກສາເພີ່ມເຕີມ."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"ທ່ານມີຂໍ້ຄວາມໃໝ່"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"ເປີດແອັບ SMS ເພື່ອເບິ່ງ"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"ບາງຄວາມສາມາດນຳໃຊ້ອາດຈະຖືກຈຳກັດ"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"ຖອນປັກໝຸດ"</string>
     <string name="app_info" msgid="6856026610594615344">"ຂໍ້ມູນແອັບ"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ແຕະເພື່ອສຶກສາເພີ່ມເຕີມ."</string>
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 8f29a84..0efdfca 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1153,8 +1153,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Pranešimų skaitymo priemonė"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Virtualiosios realybės apdorojimo priemonė"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Sąlygos teikėjas"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Pranešimų reitingavimo paslauga"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN suaktyvintas"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN suaktyvino „<xliff:g id="APP">%s</xliff:g>“"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Palieskite, kad valdytumėte tinklą."</string>
@@ -1588,8 +1587,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Darbo režimas išjungtas"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Leisti veikti darbo profiliui, įskaitant programas, sinchronizavimą fone ir susijusias funkcijas."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Įjungti"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s išjungtas"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Išjungė %1$s administratorius. Kad sužinotumėte daugiau, susisiekite su juo."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Turite naujų pranešimų"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Atidaryti SMS programą, norint peržiūrėti"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Kai kurios funkcijos gali būti ribojamos"</string>
@@ -1603,8 +1600,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Atsegti"</string>
     <string name="app_info" msgid="6856026610594615344">"Programos informacija"</string>
     <string name="negative_duration" msgid="5688706061127375131">"–<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Palieskite, kad sužinotumėte daugiau."</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 4456d19..f5c5921 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1143,11 +1143,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fona tapete"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Tapetes maiņa"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Paziņojumu uztvērējs"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR klausītājs"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Nosacījumu sniedzējs"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Paziņojumu ranžēšanas pakalpojums"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ir aktivizēts."</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Lietojumprogramma <xliff:g id="APP">%s</xliff:g> aktivizēja VPN."</string>
     <string name="vpn_text" msgid="3011306607126450322">"Pieskarieties, lai pārvaldītu tīklu."</string>
@@ -1570,8 +1568,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Darba režīms IZSLĒGTS"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Atļaujiet darboties darba profilam, tostarp lietotnēm, sinhronizācijai fonā un saistītajām funkcijām."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Ieslēgt"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Pakotne %1$s atspējota"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Atspējoja %1$s administrators. Lai uzzinātu vairāk, sazinieties ar administratoru."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Jums ir jaunas īsziņas."</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Lai skatītu, atveriet īsziņu lietotni."</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Funkcijas var būt ierobežotas"</string>
@@ -1585,8 +1581,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Atspraust"</string>
     <string name="app_info" msgid="6856026610594615344">"Lietotnes informācija"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Pieskarieties, lai uzzinātu vairāk."</string>
 </resources>
diff --git a/core/res/res/values-mcc232-mnc11/config.xml b/core/res/res/values-mcc232-mnc11/config.xml
new file mode 100644
index 0000000..91e37b4
--- /dev/null
+++ b/core/res/res/values-mcc232-mnc11/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ ** Copyright 2016, 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">
+    <!-- Don't use roaming icon for considered operators -->
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>23201</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc232-mnc12/config.xml b/core/res/res/values-mcc232-mnc12/config.xml
new file mode 100644
index 0000000..91e37b4
--- /dev/null
+++ b/core/res/res/values-mcc232-mnc12/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ ** Copyright 2016, 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">
+    <!-- Don't use roaming icon for considered operators -->
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>23201</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 0cb2d48..1fbf363 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1135,11 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Тапет"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промени тапет"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Слушател на известувања"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR слушател"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Давател на услов"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Услуга за рангирање известувања"</string>
     <string name="vpn_title" msgid="19615213552042827">"Активирана VPN"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN е активирана со <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Допри за да управуваш со мрежата."</string>
@@ -1553,8 +1551,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Режимот на работа е ИСКЛУЧЕН"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Дозволете работниот профил да функционира, вклучувајќи ги апликациите, синхронизирањето во заднина и други поврзани функции."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Вклучи"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s е оневозможен"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Оневозможено од администраторот на %1$s. Контактирајте со него за да дознаете повеќе."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Имате нови пораки"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Отворете ја апликацијата за СМС за приказ"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Некои функции се ограничени"</string>
@@ -1568,8 +1564,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Откачете"</string>
     <string name="app_info" msgid="6856026610594615344">"Информации за апликација"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Допрете за да дознаете повеќе."</string>
 </resources>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 66a7d85..2fa6786 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"അറിയിപ്പ് ലിസണർ"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR ലിസണർ"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"കണ്ടീഷൻ ദാതാവ്"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"അറിയിപ്പ് റാങ്കർ സേവനം"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN സജീവമാക്കി"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ഉപയോഗിച്ച് VPN പ്രവർത്തനക്ഷമമാക്കി"</string>
     <string name="vpn_text" msgid="3011306607126450322">"നെറ്റ്‌വർക്ക് നിയന്ത്രിക്കാൻ സ്‌പർശിക്കുക."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"ഔദ്യോഗിക മോഡ് ഓഫാണ്"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"ആപ്സും, പശ്ചാത്തല സമന്വയവും ബന്ധപ്പെട്ട ഫീച്ചറുകളും ഉൾപ്പെടെ, ഔദ്യോഗിക പ്രൊഫൈലിനെ പ്രവർത്തിക്കാൻ അനുവദിക്കുക."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"ഓണാക്കുക"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s പ്രവർത്തനരഹിതമാക്കി"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s അഡ്മിനിസ്ട്രേറ്റർ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു. കൂടുതലറിയാൻ അഡ്മിനിസ്ട്രേറ്ററെ ബന്ധപ്പെടുക."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"നിങ്ങൾക്ക് പുതിയ സന്ദേശങ്ങൾ ഉണ്ട്"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"കാണുന്നതിന് SMS ആപ്പ് തുറക്കുക"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"ചില പ്രവർത്തനക്ഷമതകൾ പരിമിതപ്പെടാം"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"അൺപിൻ ചെയ്യുക"</string>
     <string name="app_info" msgid="6856026610594615344">"ആപ്പ് വിവരം"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"കൂടുതലറിയുന്നതിന് സ്‌പർശിക്കുക."</string>
 </resources>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 566b24d..9956dbf 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Мэдэгдэл сонсогч"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR сонсогч"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Нөхцөл нийлүүлэгч"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Мэдэгдлийг ангилах үйлчилгээ"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN идэвхтэй болов"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-г <xliff:g id="APP">%s</xliff:g> идэвхтэй болгов"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Сүлжээг удирдах бол хүрнэ үү."</string>
@@ -1548,8 +1547,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Ажлын горимыг УНТРААСАН байна"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Ажлын профайлд апп, дэвсгэр синхрончлол болон бусад холбоотой тохиргоог ажиллахыг зөвшөөрнө үү."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Асаах"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s идэвхгүй болгосон"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s админ идэвхгүй болгосон. Дэлгэрэнгүй мэдэхийн тулд тэдэнтэй холбоо барина уу."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Танд шинэ зурвасууд байна"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Үзэхийн тулд SMS аппыг нээх"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Зарим үйлдэл хязгаарлалттай байж болно"</string>
@@ -1563,8 +1560,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
     <string name="app_info" msgid="6856026610594615344">"Апп-н мэдээлэл"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Дэлгэрэнгүй үзэх бол дарна уу."</string>
 </resources>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 3b38988..40f7807 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"सूचना ऐकणारा"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR श्रोता"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"अट प्रदाता"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"सूचना रॅंकर सेवा"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN सक्रिय"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> द्वारे VPN सक्रिय केले आहे"</string>
     <string name="vpn_text" msgid="3011306607126450322">"नेटवर्क व्यवस्थापित करण्यासाठी स्पर्श करा."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"कार्य मोड बंद आहे"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"कार्य प्रोफाइलला अॅप्स, पार्श्वभूमी संकालन आणि संबंधित वैशिष्ट्यांच्या समावेशासह कार्य करण्याची परवानगी द्या."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"चालू करा"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s अक्षम केले"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s प्रशासकाद्वारे अक्षम केले. अधिक जाणून घेण्‍यासाठी त्यांच्याशी संपर्क साधा."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"आपल्याकडे नवीन संदेश आहेत"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"पाहण्‍यासाठी SMS अॅप उघडा"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"काही कार्यक्षमता मर्यादित असू शकतात"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"अनपिन करा"</string>
     <string name="app_info" msgid="6856026610594615344">"अॅप माहिती"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"अधिक जाणून घेण्यासाठी स्पर्श करा."</string>
 </resources>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 9900157..2154bda 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1135,11 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Kertas dinding"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Tukar kertas dinding"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Pendengar pemberitahuan"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Pendengar VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Pembekal keadaan"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Perkhidmatan penentu kedudukan pemberitahuan"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN diaktifkan"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Sentuh untuk mengurus rangkaian."</string>
@@ -1551,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Mod kerja DIMATIKAN"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Benarkan profil kerja berfungsi, termasuk apl, penyegerakan latar belakang dan ciri yang berkaitan."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Hidupkan"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s dilumpuhkan"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Dilumpuhkan oleh pentadbir %1$s. Hubungi mereka untuk mengetahui lebih lanjut."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Anda mempunyai mesej baharu"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Buka apl SMS untuk melihat"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Sesetengah fungsi mungkin terhad"</string>
@@ -1566,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Nyahsemat"</string>
     <string name="app_info" msgid="6856026610594615344">"Maklumat apl"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Ketik untuk mengetahui lebih lanjut."</string>
 </resources>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 265a47f..4a934f0 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"အကြောင်းကြားချက် နားတောင်သူ"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR နားထောင်မှုစနစ်"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"အခြေအနေ စီမံပေးသူ"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"သတိပေးချက် အဆင့်သတ်မှတ်ခြင်းဝန်ဆောင်မှု"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ဖွင့်ထားပါသည်"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g>မှVPNအလုပ်လုပ်နေသည်"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ကွန်ရက် ထိန်းသိမ်းရန် တို့ထိပါ"</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"အလုပ်မုဒ် ပိတ်ထားသည်"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"အက်ပ်များ၊ နောက်ခံစင့်ခ်လုပ်ခြင်း၊ နှင့်သက်ဆိုင်သည့်အင်္ဂါရပ်များကို ဆောင်ရွက်ရန် အလုပ်ပရိုဖိုင်ကိုခွင့်ပြုပါ။"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"ဖွင့်ပါ"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ကိုပိတ်ထားသည်"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s စီမံခန့်ခွဲသူမှ ပိတ်ထားသည်။ ပိုမိုလေ့လာရန် ၎င်းတို့ကိုဆက်သွယ်ပါ။"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"သင့်ထံတွင် စာအသစ်များရောက်နေသည်"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"ကြည့်ရှုရန် SMS အက်ပ်ကိုဖွင့်ပါ"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"အချို့လုပ်ဆောင်ချက်များ ကန့်သတ်ချက်ရှိနိုင်သည်"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"ဖြုတ်ပါ"</string>
     <string name="app_info" msgid="6856026610594615344">"အက်ပ်အချက်အလက်"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ပိုမိုလေ့လာရန် တို့ပါ။"</string>
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index b0b21ee..79a5a86 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Varsellytteren"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Lyttetjeneste for virtuell virkelighet"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Betingelsesleverandør"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Tjeneste for rangering av varsler"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN er aktivert"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN er aktivert av <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Trykk for å administrere nettverket."</string>
@@ -1550,10 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Jobbmodus er AV"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Slå på jobbprofilen, inkludert apper, synkronisering i bakgrunnen og relaterte funksjoner."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Slå på"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s er slått av"</string>
-    <!-- String.format failed for translation -->
-    <!-- no translation found for suspended_package_message (6341091587106868601) -->
-    <skip />
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Du har nye meldinger"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Åpne SMS-appen for å se"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Enkelte funksjoner kan være begrenset"</string>
@@ -1567,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Løsne"</string>
     <string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Trykk for å finne ut mer."</string>
 </resources>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 1059a7f..db7cd01 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1143,8 +1143,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"सूचना सुन्नेवाला"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR श्रोता"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"सर्त प्रदायक"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"सूचनालाई श्रेणी प्रदान गर्ने सेवा"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN सक्रिय भयो"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN <xliff:g id="APP">%s</xliff:g>द्वारा सक्रिय गरिएको हो"</string>
     <string name="vpn_text" msgid="3011306607126450322">"नेटवर्क प्रबन्ध गर्न छुनुहोस्।"</string>
@@ -1556,8 +1555,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"कार्य मोड बन्द छ"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"अनुप्रयोग, पृष्ठभूमि सिंक र सम्बन्धित विशेषताहरू सहित, कार्य प्रोफाइललाई कार्य गर्न अनुमति दिनुहोस्।"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"सक्रिय गर्नुहोस्"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s असक्षम भयो"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s प्रशासकद्वारा असक्षम गरिएको। थप जान्नका लागि तिनीहरूलाई सम्पर्क गर्नुहोस्।"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"तपाईंलाई नयाँ सन्देश आएको छ"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"हेर्नका लागि SMS अनुप्रयोग खोल्नुहोस्"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"केही कार्य सीमित हुनसक्छ"</string>
@@ -1571,8 +1568,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"अनपिन गर्नुहोस्"</string>
     <string name="app_info" msgid="6856026610594615344">"अनुप्रयोगका बारे जानकारी"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"थप जान्नका लागि छुनुहोस्।"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 8e030dd..c7c95e19 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Listener voor meldingen"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR-listener"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provider van voorwaarden"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Rangschikkingsservice voor meldingen"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN is geactiveerd"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN wordt geactiveerd door <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Raak aan om het netwerk te beheren."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Werkmodus is UIT"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Functioneren van werkprofiel toestaan, waaronder apps, synchronisatie op de achtergrond en gerelateerde functies."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Inschakelen"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s is uitgeschakeld"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Uitgeschakeld door de beheerder van %1$s. Neem voor meer informatie contact op met de beheerder."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Je hebt nieuwe berichten"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Open je sms-app om ze te bekijken"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Bepaalde functionaliteit kan zijn beperkt"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Losmaken"</string>
     <string name="app_info" msgid="6856026610594615344">"App-info"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tik voor meer informatie."</string>
 </resources>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index 93e8181..cbb2628 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ਸੂਚਨਾ ਸੁਣਨ ਵਾਲਾ"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR ਸਰੋਤਾ"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ਸਥਿਤੀ ਪ੍ਰਦਾਤਾ"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"ਸੂਚਨਾ ਰੈਂਕਰ ਸੇਵਾ"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ਸਕਿਰਿਆ ਕੀਤਾ"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN <xliff:g id="APP">%s</xliff:g> ਰਾਹੀਂ ਸਕਿਰਿਆ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ਨੈਟਵਰਕ ਵਿਵਸਥਿਤ ਕਰਨ ਲਈ ਛੋਹਵੋ।"</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"ਕੰਮ ਮੋਡ ਬੰਦ ਹੈ"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"ਐਪਾਂ, ਬੈਕਗ੍ਰਾਊਂਡ ਸਮਕਾਲੀਕਰਨ, ਅਤੇ ਸਬੰਧਿਤ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਸ਼ਾਮਲ ਕਰਦੇ ਹੋਏ ਕੰਮ ਪ੍ਰੋਫਾਈਲ ਨੂੰ ਕੰਮ ਕਰਨ ਦੀ ਮਨਜ਼ੂਰੀ ਦਿਓ।"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"ਚਾਲੂ ਕਰੋ"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ। ਹੋਰ ਜਾਣਨ ਲਈ ਉਹਨਾਂ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"ਤੁਹਾਨੂੰ ਨਵੇਂ ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਹੋਏ ਹਨ"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"ਵੇਖਣ ਲਈ SMS ਐਪ ਖੋਲ੍ਹੋ"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"ਕੁਝ ਪ੍ਰਕਾਰਜਾਤਮਕਤਾ ਸੀਮਿਤ ਹੋ ਸਕਦੀ ਹੈ"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"ਅਨਪਿੰਨ ਕਰੋ"</string>
     <string name="app_info" msgid="6856026610594615344">"ਐਪ ਜਾਣਕਾਰੀ"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ਹੋਰ ਜਾਣਨ ਲਈ ਸਪਰਸ਼ ਕਰੋ।"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index ae801ae..5eb6b56 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1153,8 +1153,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Odbiornik powiadomień"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Odbiornik rzeczywistości wirtualnej"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Dostawca warunków"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Usługa rankingu powiadomień"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktywny"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Obsługa sieci VPN została włączona przez aplikację <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotknij, aby zarządzać siecią."</string>
@@ -1588,8 +1587,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Tryb pracy jest WYŁĄCZONY"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Włącz profil do pracy, w tym aplikacje, synchronizację w tle i inne funkcje."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Włącz"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Wyłączono pakiet %1$s"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Wyłączone przez administratora organizacji %1$s. Skontaktuj się z nim, by dowiedzieć się więcej."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Masz nowe wiadomości"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Otwórz aplikację do SMS-ów, by wyświetlić wiadomość"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Niektóre funkcje mogą być niedostępne"</string>
@@ -1603,8 +1600,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Odepnij"</string>
     <string name="app_info" msgid="6856026610594615344">"O aplikacji"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Kliknij, by dowiedzieć się więcej."</string>
 </resources>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index ce7d77f..21f6665 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Ouvinte de notificações"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Ouvinte de RV"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provedor de condições"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Serviço de classificação de notificação"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ativada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A VPN está ativada por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toque para gerenciar a rede."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabalho DESATIVADO"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Permitir que o perfil de trabalho funcione, incluindo apps, sincronização em segundo plano e recursos relacionados"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Ativar"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s desativado"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Desativado pelo administrador de %1$s. Entre em contato com ele para saber mais."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Você tem mensagens novas"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Abra o app de SMS para ver"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Algumas funcionalidades são limitadas"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Liberar guia"</string>
     <string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string>
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index a25cbfe..011ad4e 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Serviço de escuta de notificações"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Serviço de escuta de RV"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Fornecedor de condição"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Serviço de classificação de notificações"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ativada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A VPN foi ativada pelo <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toque para gerir a rede."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabalho DESATIVADO"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Permitir o funcionamento do perfil de trabalho, incluindo as aplicações, a sincronização em segundo plano e as funcionalidades relacionadas."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Ativar"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s desativado"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Desativado pelo administrador de %1$s. Contacte-o para saber mais."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Tem mensagens novas"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Abra a aplicação de SMS para ver"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Algumas funcionalid. limitadas"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Soltar"</string>
     <string name="app_info" msgid="6856026610594615344">"Informações da aplicação"</string>
     <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string>
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index ce7d77f..21f6665 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Ouvinte de notificações"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Ouvinte de RV"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provedor de condições"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Serviço de classificação de notificação"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ativada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A VPN está ativada por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toque para gerenciar a rede."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabalho DESATIVADO"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Permitir que o perfil de trabalho funcione, incluindo apps, sincronização em segundo plano e recursos relacionados"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Ativar"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s desativado"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Desativado pelo administrador de %1$s. Entre em contato com ele para saber mais."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Você tem mensagens novas"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Abra o app de SMS para ver"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Algumas funcionalidades são limitadas"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Liberar guia"</string>
     <string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string>
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 16b0312..fe5139e 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1145,8 +1145,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Serviciu de citire a notificărilor"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Instrument de ascultare pentru Realitatea virtuală"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Furnizor de condiții"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Serviciul de clasificare a notificărilor"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activat"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN este activată de <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Atingeți pentru a gestiona rețeaua."</string>
@@ -1569,8 +1568,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Modul de serviciu e DEZACTIVAT"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Permiteți profilului de serviciu să funcționeze, inclusiv aplicațiile, sincronizarea în fundal și funcțiile asociate."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Activați"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Dezactivat de %1$s"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Dezactivat de administratorul companiei %1$s. Contactați-l pentru a afla mai multe."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Aveți mesaje noi"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Deschideți aplicația pentru SMS-uri ca să vizualizați"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Unele funcții ar putea fi limitate"</string>
@@ -1584,8 +1581,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Anulați fixarea"</string>
     <string name="app_info" msgid="6856026610594615344">"Informații despre aplicație"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Atingeți pentru a afla mai multe."</string>
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 971dbfb..40c8551 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1151,11 +1151,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновый рисунок"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Сменить обои"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Служба просмотра уведомлений"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR-режим"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Поставщик условий"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Сервис для оценки важности уведомлений"</string>
     <string name="vpn_title" msgid="19615213552042827">"Сеть VPN активна"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Сеть VPN активирована приложением <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Нажмите, чтобы открыть настройки."</string>
@@ -1589,8 +1587,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Рабочий режим отключен"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Включить рабочий профиль: приложения, фоновую синхронизацию и связанные функции."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Включить"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Пакет \"%1$s\" заблокирован"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Пакет заблокирован администратором компании \"%1$s\". Обратитесь к нему за дополнительной информацией."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Новые сообщения"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Чтобы просмотреть, откройте приложение для обмена SMS"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Некоторые функции недоступны"</string>
@@ -1604,8 +1600,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Открепить"</string>
     <string name="app_info" msgid="6856026610594615344">"О приложении"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Нажмите, чтобы узнать больше."</string>
 </resources>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index ca638fa0..4f0c971 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1139,8 +1139,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"දැනුම්දීම් අසන්නා"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR සවන් දෙන්නා"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"තත්ත්වය සපයන්නා"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"දැනුම්දීම් ශ්‍රේණිගත කිරීමේ සේවාව"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ක්‍රියාත්මකයි"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> මඟින් VPN සක්‍රීය කරන ලදි"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ජාලය කළමනාකරණය කිරීමට ස්පර්ශ කරන්න."</string>
@@ -1552,8 +1551,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"වැඩ ප්‍රකාරය ක්‍රියාවිරහිතයි"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"යෙදුම්, පසුබිම සමමුහුර්ත කිරීම, සහ සම්බන්ධිත විශේෂාංග ඇතුළුව, ක්‍රියා කිරීමට කාර්යාල පැතිකඩට ඉඩ දෙන්න"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"ක්‍රියාත්මක කරන්න"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s අබල කරන ලදී"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s පරිපාලක විසින් අබල කරන ලදී. තව දැන ගැනීමට ඔවුන් අමතන්න."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"ඔබට නව පණිවිඩ තිබේ"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"බැලීමට විවෘත SMS යෙදුම විවෘත කරන්න"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"ඇතැම් ක්‍රියාකාරිත්ව සීමිත විය හැකිය"</string>
@@ -1567,8 +1564,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"ගලවන්න"</string>
     <string name="app_info" msgid="6856026610594615344">"යෙදුම් තොරතුරු"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"තව දැන ගැනීමට ස්පර්ශ කරන්න."</string>
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index e33a623..4630434 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1153,8 +1153,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Aplikácia na počúvanie upozornení"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Prijímač VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Poskytovateľ podmienky"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Služba na hodnotenie upozornení"</string>
     <string name="vpn_title" msgid="19615213552042827">"Sieť VPN je aktivovaná"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikáciu <xliff:g id="APP">%s</xliff:g> aktivovala sieť VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotykom môžete spravovať sieť."</string>
@@ -1588,8 +1587,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Pracovný režim je VYPNUTÝ"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Povoľte fungovanie pracovného profilu vrátane aplikácií, synchronizácie na pozadí a súvisiacich funkcií."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Zapnúť"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Balík %1$s bol zakázaný"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Zakázané správcom %1$s. Ak chcete získať ďalšie informácie, kontaktujte ho."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Máte nové správy."</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorte aplikáciu pre SMS a zobrazte správu"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Niektoré funkcie môžu byť obmedzené"</string>
@@ -1603,8 +1600,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Uvoľniť"</string>
     <string name="app_info" msgid="6856026610594615344">"Info o aplikácii"</string>
     <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Klepnutím získate ďalšie informácie."</string>
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 9661b82..bf60752 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1153,8 +1153,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Poslušalec obvestil"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Poslušalec za navidezno resničnost"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Ponudnik pogojev"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Storitev za določanje stopenj pomembnosti obvestil"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviran"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN je aktivirala aplikacija <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotaknite se, če želite upravljati omrežje."</string>
@@ -1588,8 +1587,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Delovni način IZKLOPLJEN"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Dovoljeno delovanje delovnega profila, vključno z aplikacijami, sinhronizacijo v ozadju in povezanimi funkcijami."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Vklop"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s – onemogočeno"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Onemogočil skrbnik %1$s. Za več informacij se obrnite nanj."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Imate nova sporočila."</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Za ogled odprite aplikacijo za SMS-je"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Nekatere funkcije bodo omejene"</string>
@@ -1603,8 +1600,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Odpenjanje"</string>
     <string name="app_info" msgid="6856026610594615344">"Podatki o aplikaciji"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dotaknite se, če želite izvedeti več."</string>
 </resources>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index a8f44d1..8b78c76 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1135,11 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imazhi i sfondit"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ndrysho imazhin e sfondit"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Dëgjues njoftimesh"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"Dëgjues VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Ofrues kushtesh"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Shërbimi i klasifikimit të njoftimeve"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN-ja u aktivizua"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-ja është aktivizuar nga <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Prek për të menaxhuar rrjetin."</string>
@@ -1551,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Modaliteti i punës është JOAKTIV"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Lejoje profilin e punës të funksionojë, duke përfshirë aplikacionet, sinkronizimin në sfond dhe funksionet e lidhura."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivizo"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s është çaktivizuar"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Çaktivizuar nga administratori i %1$s. Kontaktoje për të mësuar më shumë."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Ke mesazhe të reja"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Hap aplikacionin SMS për ta parë"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Disa funksione mund të jenë të kufizuara"</string>
@@ -1566,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Zhgozhdo"</string>
     <string name="app_info" msgid="6856026610594615344">"Informacioni mbi aplikacionin"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Prek për të mësuar më shumë."</string>
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index f771dec..c68ec88 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1145,8 +1145,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Монитор обавештења"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Обрађивач за виртуелну реалност"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Добављач услова"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Услуга рангирања обавештења"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN је активиран"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Апликација <xliff:g id="APP">%s</xliff:g> је активирала VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Додирните да бисте управљали мрежом."</string>
@@ -1569,8 +1568,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Режим за Work је ИСКЉУЧЕН"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Дозвољава профилу за Work да функционише, укључујући апликације, синхронизацију у позадини и сродне функције."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Укључи"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Пакет %1$s је онемогућен"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Онемогућио је администратор компаније %1$s. Контактирајте га да бисте сазнали више."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Имате нове поруке"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Отворите апликацију за SMS да бисте прегледали"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Неке функције су можда ограничене"</string>
@@ -1584,8 +1581,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Откачи"</string>
     <string name="app_info" msgid="6856026610594615344">"Информације о апликацији"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Додирните да бисте сазнали више."</string>
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 5a86879..46b1bf6 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Meddelandelyssnare"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Lyssnare för virtuell verklighet"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Leverantör"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Rankningstjänst för aviseringar"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN är aktiverat"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveras av <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tryck om du vill hantera nätverket."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Arbetsläget är inaktiverat"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Tillåt att jobbprofilen är aktiv, inklusive appar, bakgrundssynkronisering och andra tillhörande funktioner."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivera"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s har inaktiverats"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Inaktiverat av administratören för %1$s. Kontakta administratören om du vill veta mer."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Du har nya meddelanden"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Öppna sms-appen och visa meddelandet"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Vissa funktioner är begränsade"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Lossa"</string>
     <string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
     <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tryck här om du vill läsa mer."</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index aeac0ad..fa3d151 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1139,8 +1139,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Kisikilizi cha arifa"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Kisikilizaji cha Uhalisia Pepe"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Mtoa masharti"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Huduma ya kupanga arifa"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN imewezeshwa"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN imeamilishwa na <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Gusa ili kudhibiti mtandao."</string>
@@ -1552,8 +1551,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Hali ya kazi IMEZIMWA"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Ruhusu wasifu wa kazini utumike, ikiwa ni pamoja na programu, usawazishaji wa chini chini na vipengele vinavyohusiana."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Washa"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Imezimwa na %1$s"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Imezimwa na msimamizi wa %1$s. Wasiliana naye ili upate maelezo zaidi."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Una ujumbe mpya"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Fungua programu ya SMS ili uweze kuangalia"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Huenda baadhi ya utendaji ukawa vikwazo"</string>
@@ -1567,8 +1564,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Bandua"</string>
     <string name="app_info" msgid="6856026610594615344">"Maelezo ya programu"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Gusa ili kupata maelezo zaidi."</string>
 </resources>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index baa2c7b..57bde42 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1135,11 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"வால்பேப்பர்"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"வால்பேப்பரை மாற்று"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"அறிவிப்புகளைக் கண்காணிக்கும் சேவை"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR லிஷனர்"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"நிபந்தனை வழங்குநர்"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"அறிவிப்பை மதிப்பீடு செய்யும் சேவை"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN செயல்படுத்தப்பட்டது"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ஆல் VPN செயல்படுத்தப்பட்டது"</string>
     <string name="vpn_text" msgid="3011306607126450322">"நெட்வொர்க்கை நிர்வகிக்கத் தொடவும்."</string>
@@ -1551,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"பணிப் பயன்முறை முடக்கப்பட்டது"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"செயல்பட, பணி சுயவிவரத்தை அனுமதி. இதில் பயன்பாடுகள், பின்னணி ஒத்திசைவு மற்றும் தொடர்புடைய அம்சங்கள் அடங்கும்."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"இயக்கு"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s முடக்கப்பட்டது"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s நிர்வாகி முடக்கியுள்ளார். மேலும் அறிய, அவரைத் தொடர்புகொள்ளவும்."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"புதிய செய்திகள் வந்துள்ளன"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"பார்க்க, SMS பயன்பாட்டைத் திறக்கவும்"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"சில செயல்பாடு வரம்பிடப்பட்டிருக்கலாம்"</string>
@@ -1566,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"பின்னை அகற்று"</string>
     <string name="app_info" msgid="6856026610594615344">"பயன்பாட்டுத் தகவல்"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"மேலும் அறிய தொடவும்."</string>
 </resources>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index d8c1e05..d2381fc0 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"నోటిఫికేషన్ పరిశీలన"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR పరిశీలన"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"షరతు ప్రదాత"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"నోటిఫికేషన్ ర్యాంకర్ సేవ"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN సక్రియం చేయబడింది"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ద్వారా VPN సక్రియం చేయబడింది"</string>
     <string name="vpn_text" msgid="3011306607126450322">"నెట్‌వర్క్‌ను నిర్వహించడానికి తాకండి."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"కార్యాలయ మోడ్ ఆఫ్ చేయబడింది"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"అనువర్తనాలు, నేపథ్య సమకాలీకరణ మరియు సంబంధిత లక్షణాలతో సహా కార్యాలయ ప్రొఫైల్‌ను పని చేయడానికి అనుమతించండి."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"ఆన్ చేయి"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$sని నిలిపివేసారు"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$sని నిర్వాహకుడు నిలిపివేసారు. మరింత తెలుసుకోవడానికి వారిని సంప్రదించండి."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"మీకు కొత్త సందేశాలు ఉన్నాయి"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"వీక్షించడానికి SMS అనువర్తనాన్ని తెరవండి"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"కొంత కార్యాచరణ పరిమితం కావచ్చు"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"అన్‌‌పిన్‌ ‌చేయి"</string>
     <string name="app_info" msgid="6856026610594615344">"అనువర్తన సమాచారం"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"మరింత తెలుసుకోవడానికి తాకండి."</string>
 </resources>
diff --git a/core/res/res/values-television/config.xml b/core/res/res/values-television/config.xml
index ae19150..58d3d91 100644
--- a/core/res/res/values-television/config.xml
+++ b/core/res/res/values-television/config.xml
@@ -25,7 +25,7 @@
     <bool name="config_defaultWindowFeatureOptionsPanel">false</bool>
 
     <!-- Default bounds [left top right bottom] on screen for picture-in-picture windows. -->
-    <string translatable="false" name="config_defaultPictureInPictureBounds">"1420 100 1820 325"</string>
+    <string translatable="false" name="config_defaultPictureInPictureBounds">"1328 54 1808 324"</string>
 
     <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows, when the PIP
          is located in center. -->
@@ -33,5 +33,5 @@
 
     <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
          when the PIP is shown with Recents. -->
-    <string translatable="false" name="config_pictureInPictureBoundsInRecents">"1480 123 1760 303"</string>
+    <string translatable="false" name="config_pictureInPictureBoundsInRecents">"1484 96 1804 276"</string>
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 0b0805c..1eedd01 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ตัวฟังการแจ้งเตือน"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Listener ความเป็นจริงเสมือน"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ผู้เสนอเงื่อนไข"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"บริการตัวจัดอันดับการแจ้งเตือน"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN เปิดใช้งานแล้ว"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"เปิดใช้งาน VPN โดย <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"แตะเพื่อจัดการเครือข่าย"</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"โหมดทำงานปิดอยู่"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"อนุญาตให้โปรไฟล์งานทำงานได้ ซึ่งรวมถึงแอป การซิงค์ในพื้นหลัง และคุณลักษณะอื่นที่เกี่ยวข้อง"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"เปิด"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"ปิดใช้ %1$s แล้ว"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"ผู้ดูแลระบบ %1$s ได้ปิดใช้แล้ว โปรดสอบถามข้อมูลเพิ่มเติมจากเขา"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"คุณมีข้อความใหม่"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"เปิดแอป SMS เพื่อดู"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"อาจมีข้อจำกัดในบางฟังก์ชัน"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"เลิกปักหมุด"</string>
     <string name="app_info" msgid="6856026610594615344">"ข้อมูลแอป"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"แตะเพื่อเรียนรู้เพิ่มเติม"</string>
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index ed669c4..d785cf4 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR listener"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Nagbibigay ng kundisyon"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Serbisyo sa pag-rank ng notification"</string>
     <string name="vpn_title" msgid="19615213552042827">"Naka-activate ang VPN"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Isinaaktibo ang VPN ng <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Pindutin upang pamahalaan ang network."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"NAKA-OFF ang work mode"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Payagang gumana ang profile sa trabaho, kasama na ang mga app, pag-sync sa background at mga may kaugnayang feature."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"I-on"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"Na-disable ang %1$s"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Na-disable ng administrator ng %1$s. Makipag-ugnayan sa administrator upang matuto nang higit pa."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Mayroon kang mga bagong mensahe"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Buksan ang SMS app upang tingnan"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Limitado ilang functionality"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"I-unpin"</string>
     <string name="app_info" msgid="6856026610594615344">"Impormasyon ng app"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Pindutin upang matuto nang higit pa."</string>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 588ed7a..d4f2891 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Bildirim dinleyici"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Sanal Gerçeklik dinleyici"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Durum sağlayıcı"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Bildirim sıralama hizmeti"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN etkinleştirildi"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN, <xliff:g id="APP">%s</xliff:g> tarafından etkinleştirildi"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Ağı yönetmek için dokunun."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"İş modu KAPALI"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Uygulamalar, arka planda senkronizasyon ve ilgili özellikler dahil olmak üzere iş profilinin çalışmasına izin ver."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Aç"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s devre dışı bırakıldı"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s yöneticisi tarafından devre dışı bırakıldı. Daha fazla bilgi edinmek için kendileriyle iletişime geçin."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Yeni mesajlarınız var"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Görüntülemek için SMS uygulamasını açın"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Bazı işlevler sınırlı olabilir"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Sabitlemeyi kaldır"</string>
     <string name="app_info" msgid="6856026610594615344">"Uygulama bilgileri"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Daha fazla bilgi edinmek için dokunun."</string>
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 5ed4018..aba18b5 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1153,8 +1153,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Служба читання сповіщень"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Обробник віртуальної реальності"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Постачальник умов"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Служба встановлення пріоритетності сповіщень"</string>
     <string name="vpn_title" msgid="19615213552042827">"Мережу VPN активовано"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Мережу VPN активовано програмою <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Торкніться, щоб керувати мережею."</string>
@@ -1588,8 +1587,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Робочий профіль ВИМКНЕНО"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Увімкнути робочий профіль, зокрема додатки, фонову синхронізацію та пов’язані функції."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Увімкнути"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s вимкнено"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Вимкнув адміністратор %1$s. Зв’яжіться з ним, щоб дізнатися більше."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"У вас є нові повідомлення"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Щоб переглянути, відкрийте додаток для SMS"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Деякі функції можуть не працювати"</string>
@@ -1603,8 +1600,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Відкріпити"</string>
     <string name="app_info" msgid="6856026610594615344">"Про додаток"</string>
     <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Торкніться, щоб дізнатися більше."</string>
 </resources>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index faa01b7..47e6e88 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1135,11 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"وال پیپر"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"وال پیپر تبدیل کریں"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"اطلاع سننے والا"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"‏VR سامع"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"شرط فراہم کنندہ"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"اطلاع کی درجہ بندی سروس"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏VPN فعال ہوگیا"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏<xliff:g id="APP">%s</xliff:g> کے ذریعہ VPN فعال ہے"</string>
     <string name="vpn_text" msgid="3011306607126450322">"نیٹ ورک کا نظم کرنے کیلئے چھوئیں۔"</string>
@@ -1551,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"کام موڈ آف ہے"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"دفتری پروفائل کو کام کرنے دیں، بشمول ایپس، پس منظر کی مطابقت پذیری اور متعلقہ خصوصیات۔"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"آن کریں"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"‏%1$s غیر فعال کردہ"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"‏%1$s منتظم کی جانب سے غیر فعال کر دیا گیا۔ مزید جاننے کیلئے ان سے رابطہ کریں۔"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"آپ کے پاس نئے پیغامات ہیں"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"‏دیکھنے کیلئے SMS ایپ کھولیں"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"کچھ فعالیت محدود ہو سکتی ہے"</string>
@@ -1566,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"پن ہٹائیں"</string>
     <string name="app_info" msgid="6856026610594615344">"ایپ کی معلومات"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"مزید جاننے کیلئے ٹچ کریں۔"</string>
 </resources>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 205c17b..88a417b 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1135,11 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fon rasmi"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Fon rasmini o‘zgartirish"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Bildirishnoma tinglovchisi"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR rejimi"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Shartlarni taqdim etuvchi"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Bildirishnomalarni baholash xizmati"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN faollashtirildi"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN <xliff:g id="APP">%s</xliff:g> tomonidan faollashtirilgan"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tarmoqni boshqarish uchun bosing."</string>
@@ -1551,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Ish rejimi O‘CHIQ"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Ishchi profilini yoqish: ilovalar, fonda sinxronlash va bog‘liq funksiyalar."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Yoqish"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s o‘chirilgan"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"%1$s administratori tomonidan o‘chirilgan. Batafsil ma’lumot uchun bog‘laning."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Sizga yangi SMS keldi"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Ko‘rish uchun SMS ilovasini oching"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Ba’zi funksiyalar cheklanishi m-n"</string>
@@ -1566,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Olib tashlash"</string>
     <string name="app_info" msgid="6856026610594615344">"Ilova haqida"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Ko‘proq o‘rganish uchun bosing."</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 0de9fae..b67008e 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Trình xử lý thông báo"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Trình nghe VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Trình cung cấp điều kiện"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Dịch vụ xếp hạng thông báo"</string>
     <string name="vpn_title" msgid="19615213552042827">"Đã kích hoạt VPN"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN được <xliff:g id="APP">%s</xliff:g> kích hoạt"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Chạm để quản lý mạng."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Chế độ làm việc đang TẮT"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Cho phép hồ sơ công việc hoạt động, bao gồm ứng dụng, đồng bộ hóa trong nền và các tính năng liên quan."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Bật"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s đã bị tắt"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Đã bị quản trị viên %1$s tắt. Hãy liên hệ với quản trị viên để tìm hiểu thêm."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Bạn có tin nhắn mới"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Mở ứng dụng SMS để xem"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Một số chức năng có thể bị hạn chế"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Bỏ ghim"</string>
     <string name="app_info" msgid="6856026610594615344">"Thông tin ứng dụng"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Chạm để tìm hiểu thêm."</string>
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 448a03e..d9e5a14 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1135,11 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁纸"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"更改壁纸"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知侦听器"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR 监听器"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"条件提供程序"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"通知重要性排序服务"</string>
     <string name="vpn_title" msgid="19615213552042827">"已激活VPN"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g>已激活VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"触摸可管理网络。"</string>
@@ -1551,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"工作模式已关闭"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"启用工作资料,包括应用、后台同步和相关功能。"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"开启"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"%1$s已被禁用"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"该软件包已被%1$s管理员禁用。请与管理员联系以了解详情。"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"您有新消息"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"打开短信应用查看"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"部分功能可能会受到限制"</string>
@@ -1566,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
     <string name="app_info" msgid="6856026610594615344">"应用信息"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"触摸即可了解详情。"</string>
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 35300d4..64de938 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知接聽器"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"虛擬現實接聽器"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"條件供應商"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"通知排序服務"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN 已啟用。"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> 已啟用 VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"輕觸即可管理網絡。"</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"工作模式已關閉"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"允許使用應用程式、背景同步及相關功能的工作設定檔。"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"開啟"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"已停用「%1$s」"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"「%1$s」管理員已停用此套件。請與管理員聯絡以瞭解詳情。"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"您有新的訊息"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"開啟短訊應用程式查看內容"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"部分功能可能會受到限制"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
     <string name="app_info" msgid="6856026610594615344">"應用程式資料"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"輕觸以瞭解詳情。"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 946c5cc..756c52d 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1135,11 +1135,9 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"桌布"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"變更桌布"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知接聽器"</string>
-    <!-- no translation found for vr_listener_binding_label (4316591939343607306) -->
-    <skip />
+    <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR 接聽器"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"條件提供者"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"通知重要性排序服務"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN 已啟用"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> 已啟用 VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"輕觸即可管理網路。"</string>
@@ -1551,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Work 模式已關閉"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"啟用 Work 設定檔,包括應用程式、背景同步處理和相關功能。"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"開啟"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"已由「%1$s」停用"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"這個套件已由「%1$s」管理員停用。請與對方聯絡以瞭解詳情。"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"您有新訊息"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"開啟簡訊應用程式來查看內容"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"部分功能可能受到鎖定"</string>
@@ -1566,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
     <string name="app_info" msgid="6856026610594615344">"應用程式資訊"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"輕觸即可瞭解詳情。"</string>
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 6af695d..6ff550b 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1137,8 +1137,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Umlaleli wesaziso"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Isilaleli se-VR"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Umhlinzeki wesimo"</string>
-    <!-- no translation found for notification_ranker_binding_label (774540592299064747) -->
-    <skip />
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"Isevisi yesilinganisi sesaziso"</string>
     <string name="vpn_title" msgid="19615213552042827">"I-VPN isiyasebenza"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"i-VPN ivuswe ngu <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Thinta ukuze wengamele inethiwekhi."</string>
@@ -1550,8 +1549,6 @@
     <string name="work_mode_off_title" msgid="8954725060677558855">"Imodi yomsebenzi IVALIWE"</string>
     <string name="work_mode_off_message" msgid="3286169091278094476">"Vumela iphrofayela yomsebenzi ukuze isebenze, efaka izinhlelo zokusebenza, ukuvumelanisa kwangemuva, nezici ezisondelene."</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"Vula"</string>
-    <string name="suspended_package_title" msgid="3408150347778524435">"I-%1$s ikhutshaziwe"</string>
-    <string name="suspended_package_message" msgid="6341091587106868601">"Ikhutshazwe umlawuli we-%1$s. Xhumana nabo ukuze ufunde kabanzi."</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"Unemilayezo emisha"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"Vula uhlelo lokusebenza lwe-SMS ukuze ubuke"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"Okunye ukusebenza kungakhawulelwe"</string>
@@ -1565,8 +1562,7 @@
     <string name="unpin_target" msgid="3556545602439143442">"Susa ukuphina"</string>
     <string name="app_info" msgid="6856026610594615344">"Ulwazi lohlelo lokusebenza"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <!-- no translation found for audit_safemode_notification (6351827251856877200) -->
+    <!-- no translation found for audit_safemode_notification (6416076898350685856) -->
     <skip />
-    <!-- no translation found for audit_safemode_notification_details (1860601176690176413) -->
-    <skip />
+    <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Thinta ukuze ufunde kabanzi."</string>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9ccd7f0..a52c4e5 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -593,6 +593,9 @@
              the appearance matches the branding of the app requesting the fingerprint scan.-->
         <attr name="fingerprintAuthDrawable" format="reference" />
 
+	<!-- Asset that should be used to show users the position of the NFC antenna on the device. -->
+	<attr name="nfcAntennaPositionDrawable" format="reference" />
+
         <!-- ============ -->
         <!-- Panel styles -->
         <!-- ============ -->
@@ -5873,6 +5876,12 @@
         </attr>
         <!-- sets the Miter limit for a stroked path -->
         <attr name="strokeMiterLimit" format="float"/>
+        <!-- sets the fillType for a path. It is the same as SVG's "fill-rule" properties.
+             For more details, see https://www.w3.org/TR/SVG/painting.html#FillRuleProperty -->
+        <attr name="fillType" format="enum">
+            <enum name="nonZero" value="0"/>
+            <enum name="evenOdd" value="1"/>
+        </attr>
     </declare-styleable>
 
     <!-- Defines the clip path used in VectorDrawables. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7857107..01b2c47 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -805,6 +805,13 @@
     -->
     <integer name="config_longPressOnPowerBehavior">1</integer>
 
+    <!-- Control the behavior when the user long presses the back button.  Non-zero values are only
+         valid for watches as part of CDD/CTS.
+            0 - Nothing
+            1 - Go to voice assist
+    -->
+    <integer name="config_longPressOnBackBehavior">0</integer>
+
     <!-- Control the behavior when the user short presses the power button.
             0 - Nothing
             1 - Go to sleep (doze)
@@ -1853,6 +1860,10 @@
         <item>-1</item>
     </integer-array>
 
+    <!-- When true, local displays that do not contain any of their own content will automatically
+         mirror the content of the default display. -->
+    <bool name="config_localDisplaysMirrorContent">true</bool>
+
     <!-- When true use the linux /dev/input/event subsystem to detect the switch changes
          on the headphone/microphone jack. When false use the older uevent framework. -->
     <bool name="config_useDevInputEventForAudioJack">false</bool>
@@ -2440,9 +2451,13 @@
          flag). -->
     <bool name="config_forceWindowDrawsStatusBarBackground">true</bool>
 
-    <!-- If set, this will force the navigation bar to always be drawn with an opaque
-         background. -->
-    <bool name="config_forceNavBarAlwaysOpaque">false</bool>
+    <!-- Controls the opacity of the navigation bar depending on the visibility of the
+         various workspace stacks.
+         0 - Nav bar is always opaque when either the freeform stack or docked stack is visible.
+         1 - Nav bar is always translucent when the freeform stack is visible, otherwise always
+         opaque.
+         -->
+    <integer name="config_navBarOpacityMode">0</integer>
 
     <!-- Default bounds [left top right bottom] on screen for picture-in-picture windows. -->
     <string translatable="false" name="config_defaultPictureInPictureBounds">"0 0 100 100"</string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 152473a..081d613 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -151,16 +151,13 @@
     <dimen name="notification_content_picture_margin">56dp</dimen>
 
     <!-- height of the content margin to accomodate for the header -->
-    <dimen name="notification_content_margin_top">30dp</dimen>
+    <dimen name="notification_content_margin_top">37.5dp</dimen>
 
     <!-- height of the content margin on the bottom -->
-    <dimen name="notification_content_margin_bottom">13dp</dimen>
-
-    <!-- height of notification header view if present -->
-    <dimen name="notification_header_height">32dp</dimen>
+    <dimen name="notification_content_margin_bottom">16dp</dimen>
 
     <!-- Height of a small notification in the status bar -->
-    <dimen name="notification_min_height">84dp</dimen>
+    <dimen name="notification_min_height">92dp</dimen>
 
     <!-- The width of the big icons in notifications. -->
     <dimen name="notification_large_icon_width">64dp</dimen>
@@ -177,7 +174,7 @@
     <dimen name="media_notification_expanded_image_max_size">94dp</dimen>
 
     <!-- The maximum size of the image in the expanded media notification -->
-    <dimen name="media_notification_expanded_image_margin_bottom">16dp</dimen>
+    <dimen name="media_notification_expanded_image_margin_bottom">20dp</dimen>
 
     <!-- The margin of the content to an image-->
     <dimen name="notification_content_image_margin_end">8dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 06e2248..4e8740a 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2705,6 +2705,8 @@
     <public type="attr" name="countDown" />
     <public type="attr" name="canRecord" />
     <public type="attr" name="tunerCount" />
+    <public type="attr" name="nfcAntennaPositionDrawable" />
+    <public type="attr" name="fillType" />
 
     <public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
     <public type="style" name="Widget.Material.SeekBar.Discrete" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 17afd92..5d083d7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4188,10 +4188,6 @@
     <string name="work_mode_off_message">Allow work profile to function, including apps, background sync, and related features.</string>
     <!-- Title for button to turn on work profile. [CHAR LIMIT=NONE] -->
     <string name="work_mode_turn_on">Turn on</string>
-    <!-- Title for dialog displayed when a packge is suspended by device admin. [CHAR LIMIT=30] -->
-    <string name="suspended_package_title">%1$s disabled</string>
-    <!-- Message for dialog displayed when a packge is suspended by device admin. [CHAR LIMIT=NONE] -->
-    <string name="suspended_package_message">Disabled by %1$s administrator. Contact them to learn more.</string>
 
     <!-- Notification title shown when new SMS/MMS is received while the device is locked [CHAR LIMIT=NONE] -->
     <string name="new_sms_notification_title">You have new messages</string>
@@ -4229,7 +4225,7 @@
     <string name="negative_duration">\u2212<xliff:g id="time" example="1:14">%1$s</xliff:g></string>
 
     <!-- Title of notification shown when device has been forced to safe mode after a security compromise. -->
-    <string name="audit_safemode_notification">Factory reset to use this device normally</string>
+    <string name="audit_safemode_notification">Factory reset to use this device without restrictions</string>
     <!-- Description of notification shown when device has been forced to safe mode after a security compromise. -->
     <string name="audit_safemode_notification_details">Touch to learn more.</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index cad0e7b..f01cce3 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -306,6 +306,7 @@
   <java-symbol type="bool" name="config_freeformWindowManagement" />
   <java-symbol type="bool" name="config_supportsMultiWindow" />
   <java-symbol type="bool" name="config_guestUserEphemeral" />
+  <java-symbol type="bool" name="config_localDisplaysMirrorContent" />
   <java-symbol type="string" name="config_defaultPictureInPictureBounds" />
   <java-symbol type="string" name="config_centeredPictureInPictureBounds" />
   <java-symbol type="string" name="config_pictureInPictureBoundsInRecents" />
@@ -382,6 +383,7 @@
   <java-symbol type="integer" name="config_extraFreeKbytesAbsolute" />
   <java-symbol type="integer" name="config_immersive_mode_confirmation_panic" />
   <java-symbol type="integer" name="config_longPressOnPowerBehavior" />
+  <java-symbol type="integer" name="config_longPressOnBackBehavior" />
   <java-symbol type="integer" name="config_lowMemoryKillerMinFreeKbytesAdjust" />
   <java-symbol type="integer" name="config_lowMemoryKillerMinFreeKbytesAbsolute" />
   <java-symbol type="integer" name="config_max_pan_devices" />
@@ -2394,7 +2396,7 @@
 
   <java-symbol type="string" name="config_packagedKeyboardName" />
   <java-symbol type="bool" name="config_forceWindowDrawsStatusBarBackground" />
-  <java-symbol type="bool" name="config_forceNavBarAlwaysOpaque" />
+  <java-symbol type="integer" name="config_navBarOpacityMode" />
   <java-symbol type="color" name="system_bar_background_semi_transparent" />
 
   <!-- EditText suggestion popup. -->
@@ -2423,13 +2425,13 @@
   <java-symbol type="drawable" name="ic_collapse_notification" />
   <java-symbol type="drawable" name="ic_expand_bundle" />
   <java-symbol type="drawable" name="ic_collapse_bundle" />
-  <java-symbol type="dimen" name="notification_header_height" />
   <java-symbol type="dimen" name="notification_min_content_height" />
   <java-symbol type="dimen" name="notification_header_shrink_min_width" />
   <java-symbol type="dimen" name="notification_content_margin_start" />
   <java-symbol type="dimen" name="notification_content_margin_end" />
   <java-symbol type="dimen" name="notification_content_picture_margin" />
   <java-symbol type="dimen" name="notification_content_margin_top" />
+  <java-symbol type="dimen" name="notification_content_margin_bottom" />
   <java-symbol type="string" name="importance_from_user" />
   <java-symbol type="string" name="importance_from_person" />
 
@@ -2506,8 +2508,6 @@
   <java-symbol type="string" name="work_mode_off_title" />
   <java-symbol type="string" name="work_mode_off_message" />
   <java-symbol type="string" name="work_mode_turn_on" />
-  <java-symbol type="string" name="suspended_package_title" />
-  <java-symbol type="string" name="suspended_package_message" />
 
   <!-- New SMS notification while phone is locked. -->
   <java-symbol type="string" name="new_sms_notification_title" />
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 5970a22..a361eda 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -223,6 +223,7 @@
         <item name="textSelectHandleWindowStyle">@style/Widget.Material.TextSelectHandle</item>
         <item name="textEditSuggestionItemLayout">@layout/text_edit_suggestion_item_material</item>
         <item name="textEditSuggestionContainerLayout">@layout/text_edit_suggestion_container_material</item>
+        <item name="textEditSuggestionHighlightStyle">@style/TextAppearance.Material.TextSuggestionHighlight</item>
         <item name="textCursorDrawable">@drawable/text_cursor_material</item>
 
         <!-- Widget styles -->
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index cf7978c..c02a01a 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -102,7 +102,7 @@
     <!-- United Kingdom (Great Britain): 4-6 digits, common codes [5-8]xxxx, plus EU:
          http://www.short-codes.com/media/Co-regulatoryCodeofPracticeforcommonshortcodes170206.pdf,
          visual voicemail code for EE: 887 -->
-    <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}|887|83669|34664|40406" />
+    <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}|2020|35890|61002|61202|887|83669|34664|40406" />
 
     <!-- Georgia: 4 digits, known premium codes listed -->
     <shortcode country="ge" pattern="\\d{4}" premium="801[234]|888[239]" />
@@ -214,7 +214,7 @@
 
     <!-- USA: 5-6 digits (premium codes from https://www.premiumsmsrefunds.com/ShortCodes.htm),
          visual voicemail code for T-Mobile: 122 -->
-    <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:567|578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" free="122|87902" />
+    <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567" free="122|87902" />
 
     <!-- Vietnam -->
     <shortcode country="vn" free="5001" />
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
index c92863d..b908d92 100644
--- a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
@@ -905,6 +905,10 @@
                 a1.start();
                 a2.reverse();
                 a3.start();
+                // Check that the animators' values are immediately set to end value in the case of
+                // 0-duration.
+                assertEquals(A1_END_VALUE, a1.getAnimatedValue());
+                assertEquals(A2_START_VALUE, a2.getAnimatedValue());
             }
         });
         Thread.sleep(POLL_INTERVAL);
@@ -951,6 +955,10 @@
 
                 a1.start();
                 a2.start();
+
+                // In the case of 0 duration scale applied to a non-0 duration, check that the
+                // value is immediately set to the start value.
+                assertEquals(A2_START_VALUE, a2.getAnimatedValue());
             }
         });
         Thread.sleep(POLL_INTERVAL);
@@ -962,6 +970,8 @@
                 assertTrue(l2.startCalled);
                 assertTrue(l1.endCalled);
                 assertTrue(l2.endCalled);
+                assertEquals(A1_END_VALUE, a1.getAnimatedValue());
+                assertEquals(A2_END_VALUE, a2.getAnimatedValue());
             }
         });
 
diff --git a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
index af2a944..bae4ecc 100644
--- a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
@@ -81,8 +81,7 @@
     protected static final int DEFAULT_WAIT_POLL_TIME = 5 * 1000;  // 5 seconds
 
     protected static final int WAIT_FOR_DOWNLOAD_POLL_TIME = 1 * 1000;  // 1 second
-    protected static final int MAX_WAIT_FOR_DOWNLOAD_TIME = 5 * 60 * 1000; // 5 minutes
-    protected static final int MAX_WAIT_FOR_LARGE_DOWNLOAD_TIME = 15 * 60 * 1000; // 15 minutes
+    protected static final int MAX_WAIT_FOR_DOWNLOAD_TIME = 30 * 1000; // 30 seconds
 
     protected static final int DOWNLOAD_TO_SYSTEM_CACHE = 1;
     protected static final int DOWNLOAD_TO_DOWNLOAD_CACHE_DIR = 2;
@@ -970,7 +969,7 @@
     protected void verifyInt(Cursor cursor, String columnName, int expected) {
         int index = cursor.getColumnIndex(columnName);
         int actual = cursor.getInt(index);
-        assertEquals(expected, actual);
+        assertEquals(String.format("Expected = %d : Actual = %d", expected, actual), expected, actual);
     }
 
     /**
diff --git a/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java b/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java
index 7019980..4a53852 100644
--- a/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java
@@ -23,18 +23,16 @@
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.test.suitebuilder.annotation.LargeTest;
-
-import android.test.suitebuilder.annotation.Suppress;
 import com.google.mockwebserver.MockResponse;
 
 import java.io.File;
+import java.util.concurrent.TimeoutException;
 import java.util.Iterator;
 import java.util.Set;
 
 /**
  * Integration tests of the DownloadManager API.
  */
-@Suppress  // Failing.
 public class DownloadManagerFunctionalTest extends DownloadManagerBaseTest {
     private static final String TAG = "DownloadManagerFunctionalTest";
     private final static String CACHE_DIR =
@@ -79,7 +77,11 @@
         request.setTitle(DEFAULT_FILENAME);
 
         long dlRequest = mDownloadManager.enqueue(request);
-        waitForDownloadOrTimeout(dlRequest);
+        try {
+            waitForDownloadOrTimeout(dlRequest);
+        } catch (TimeoutException ex) {
+            // it is expected to timeout as download never finishes
+        }
 
         Cursor cursor = getCursor(dlRequest);
         try {
@@ -114,7 +116,7 @@
         verifyDownload(dlRequest, blobData);
         mDownloadManager.remove(dlRequest);
     }
-    
+
     /**
      * Helper to verify a standard single-file download from the mock server, and clean up after
      * verification
@@ -135,9 +137,7 @@
 
             verifyFileSize(pfd, fileSize);
             verifyFileContents(pfd, fileData);
-            int colIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);
-            String fileName = cursor.getString(colIndex);
-            assertTrue(fileName.startsWith(CACHE_DIR));
+            assertTrue(new File(CACHE_DIR + "/" + DEFAULT_FILENAME).exists());
         } finally {
             pfd.close();
             cursor.close();
@@ -161,7 +161,6 @@
 
             Uri localUri = Uri.fromFile(existentFile);
             request.setDestinationUri(localUri);
-
             long dlRequest = mDownloadManager.enqueue(request);
 
             // wait for the download to complete
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
index 5d46489..47554a6 100644
--- a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
+++ b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
@@ -17,20 +17,18 @@
 package android.content.res;
 
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.TypedValue;
 
 import com.android.frameworks.coretests.R;
 
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 
 public class ConfigurationBoundResourceCacheTest
         extends ActivityInstrumentationTestCase2<ResourceCacheActivity> {
 
     ConfigurationBoundResourceCache<Float> mCache;
 
-    Method mCalcConfigChanges;
-
     public ConfigurationBoundResourceCacheTest() {
         super(ResourceCacheActivity.class);
     }
@@ -41,33 +39,42 @@
         mCache = new ConfigurationBoundResourceCache<>();
     }
 
+    @SmallTest
     public void testGetEmpty() {
-        assertNull(mCache.get(-1, null));
+        final Resources res = getActivity().getResources();
+        assertNull(mCache.getInstance(-1, res, null));
     }
 
+    @SmallTest
     public void testSetGet() {
         mCache.put(1, null, new DummyFloatConstantState(5f));
-        assertEquals(5f, mCache.get(1, null));
-        assertNotSame(5f, mCache.get(1, null));
-        assertEquals(null, mCache.get(1, getActivity().getTheme()));
+        final Resources res = getActivity().getResources();
+        assertEquals(5f, mCache.getInstance(1, res, null));
+        assertNotSame(5f, mCache.getInstance(1, res, null));
+        assertEquals(null, mCache.getInstance(1, res, getActivity().getTheme()));
     }
 
+    @SmallTest
     public void testSetGetThemed() {
         mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f));
-        assertEquals(null, mCache.get(1, null));
-        assertEquals(5f, mCache.get(1, getActivity().getTheme()));
-        assertNotSame(5f, mCache.get(1, getActivity().getTheme()));
+        final Resources res = getActivity().getResources();
+        assertEquals(null, mCache.getInstance(1, res, null));
+        assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()));
+        assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()));
     }
 
+    @SmallTest
     public void testMultiThreadPutGet() {
         mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f));
         mCache.put(1, null, new DummyFloatConstantState(10f));
-        assertEquals(10f, mCache.get(1, null));
-        assertNotSame(10f, mCache.get(1, null));
-        assertEquals(5f, mCache.get(1, getActivity().getTheme()));
-        assertNotSame(5f, mCache.get(1, getActivity().getTheme()));
+        final Resources res = getActivity().getResources();
+        assertEquals(10f, mCache.getInstance(1, res, null));
+        assertNotSame(10f, mCache.getInstance(1, res, null));
+        assertEquals(5f, mCache.getInstance(1, res, getActivity().getTheme()));
+        assertNotSame(5f, mCache.getInstance(1, res, getActivity().getTheme()));
     }
 
+    @SmallTest
     public void testVoidConfigChange()
             throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
         TypedValue staticValue = new TypedValue();
@@ -83,11 +90,12 @@
                 Configuration.ORIENTATION_PORTRAIT
                 : Configuration.ORIENTATION_LANDSCAPE;
         int changes = calcConfigChanges(res, newCnf);
-        assertEquals(staticDim, mCache.get(key, getActivity().getTheme()));
+        assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()));
         mCache.onConfigurationChange(changes);
-        assertEquals(staticDim, mCache.get(key, getActivity().getTheme()));
+        assertEquals(staticDim, mCache.getInstance(key, res, getActivity().getTheme()));
     }
 
+    @SmallTest
     public void testEffectiveConfigChange()
             throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
         TypedValue changingValue = new TypedValue();
@@ -105,11 +113,12 @@
                 Configuration.ORIENTATION_PORTRAIT
                 : Configuration.ORIENTATION_LANDSCAPE;
         int changes = calcConfigChanges(res, newCnf);
-        assertEquals(changingDim, mCache.get(key, getActivity().getTheme()));
+        assertEquals(changingDim, mCache.getInstance(key, res, getActivity().getTheme()));
         mCache.onConfigurationChange(changes);
         assertNull(mCache.get(key, getActivity().getTheme()));
     }
 
+    @SmallTest
     public void testConfigChangeMultipleResources()
             throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
         TypedValue staticValue = new TypedValue();
@@ -130,17 +139,19 @@
                 Configuration.ORIENTATION_PORTRAIT
                 : Configuration.ORIENTATION_LANDSCAPE;
         int changes = calcConfigChanges(res, newCnf);
-        assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic,
+        assertEquals(staticDim, mCache.getInstance(R.dimen.resource_cache_test_generic, res,
                 getActivity().getTheme()));
-        assertEquals(changingDim, mCache.get(R.dimen.resource_cache_test_orientation_dependent,
-                getActivity().getTheme()));
+        assertEquals(changingDim,
+                mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
+                        getActivity().getTheme()));
         mCache.onConfigurationChange(changes);
-        assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic,
+        assertEquals(staticDim, mCache.getInstance(R.dimen.resource_cache_test_generic, res,
                 getActivity().getTheme()));
-        assertNull(mCache.get(R.dimen.resource_cache_test_orientation_dependent,
+        assertNull(mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
                 getActivity().getTheme()));
     }
 
+    @SmallTest
     public void testConfigChangeMultipleThemes()
             throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
         TypedValue[] staticValues = new TypedValue[]{new TypedValue(), new TypedValue()};
@@ -172,31 +183,27 @@
         int changes = calcConfigChanges(res, newCnf);
         for (int i = 0; i < 2; i++) {
             final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
-            assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic, theme));
+            assertEquals(staticDim,
+                    mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme));
             assertEquals(changingDim,
-                    mCache.get(R.dimen.resource_cache_test_orientation_dependent, theme));
+                    mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
+                            theme));
         }
         mCache.onConfigurationChange(changes);
         for (int i = 0; i < 2; i++) {
             final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
-            assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic, theme));
-            assertNull(mCache.get(R.dimen.resource_cache_test_orientation_dependent, theme));
+            assertEquals(staticDim,
+                    mCache.getInstance(R.dimen.resource_cache_test_generic, res, theme));
+            assertNull(mCache.getInstance(R.dimen.resource_cache_test_orientation_dependent, res,
+                    theme));
         }
     }
 
-    private int calcConfigChanges(Resources resources, Configuration configuration)
-            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
-        if (mCalcConfigChanges == null) {
-            mCalcConfigChanges = Resources.class.getDeclaredMethod("calcConfigChanges",
-                    Configuration.class);
-            mCalcConfigChanges.setAccessible(true);
-        }
-        return (Integer) mCalcConfigChanges.invoke(resources, configuration);
-
+    private static int calcConfigChanges(Resources resources, Configuration configuration) {
+        return resources.calcConfigChanges(configuration);
     }
 
-    static class DummyFloatConstantState extends
-            ConstantState<Float> {
+    static class DummyFloatConstantState extends ConstantState<Float> {
 
         final Float mObj;
 
diff --git a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
new file mode 100644
index 0000000..3cadbf6
--- /dev/null
+++ b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package android.content.res;
+
+import android.annotation.NonNull;
+import android.app.ResourcesManager;
+import android.os.Binder;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.DisplayMetrics;
+import android.util.LocaleList;
+import android.util.TypedValue;
+import android.view.Display;
+import junit.framework.TestCase;
+
+public class ResourcesManagerTest extends TestCase {
+    private static final String APP_ONE_RES_DIR = "app_one.apk";
+    private static final String APP_ONE_RES_SPLIT_DIR = "app_one_split.apk";
+    private static final String APP_TWO_RES_DIR = "app_two.apk";
+    private static final String LIB_RES_DIR = "lib.apk";
+
+    private ResourcesManager mResourcesManager;
+    private DisplayMetrics mDisplayMetrics;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mDisplayMetrics = new DisplayMetrics();
+        mDisplayMetrics.setToDefaults();
+
+        // Override defaults (which take device specific properties).
+        mDisplayMetrics.density = 1.0f;
+        mDisplayMetrics.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
+        mDisplayMetrics.xdpi = DisplayMetrics.DENSITY_DEFAULT;
+        mDisplayMetrics.ydpi = DisplayMetrics.DENSITY_DEFAULT;
+        mDisplayMetrics.noncompatDensity = mDisplayMetrics.density;
+        mDisplayMetrics.noncompatDensityDpi = mDisplayMetrics.densityDpi;
+        mDisplayMetrics.noncompatXdpi = DisplayMetrics.DENSITY_DEFAULT;
+        mDisplayMetrics.noncompatYdpi = DisplayMetrics.DENSITY_DEFAULT;
+
+        mResourcesManager = new ResourcesManager() {
+            @Override
+            protected AssetManager createAssetManager(@NonNull ResourcesKey key) {
+                return new AssetManager();
+            }
+
+            @Override
+            protected DisplayMetrics getDisplayMetricsLocked(int displayId) {
+                return mDisplayMetrics;
+            }
+        };
+    }
+
+    @SmallTest
+    public void testMultipleCallsWithIdenticalParametersCacheReference() {
+        Resources resources = mResourcesManager.getResources(
+                null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources);
+
+        Resources newResources = mResourcesManager.getResources(
+                null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(newResources);
+        assertSame(resources, newResources);
+    }
+
+    @SmallTest
+    public void testMultipleCallsWithDifferentParametersReturnDifferentReferences() {
+        Resources resources = mResourcesManager.getResources(
+                null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources);
+
+        Configuration overrideConfig = new Configuration();
+        overrideConfig.smallestScreenWidthDp = 200;
+        Resources newResources = mResourcesManager.getResources(
+                null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, overrideConfig,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(newResources);
+        assertNotSame(resources, newResources);
+    }
+
+    @SmallTest
+    public void testAddingASplitCreatesANewImpl() {
+        Resources resources1 = mResourcesManager.getResources(
+                null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources1);
+
+        Resources resources2 = mResourcesManager.getResources(
+                null, APP_ONE_RES_DIR, new String[] { APP_ONE_RES_SPLIT_DIR }, null, null,
+                Display.DEFAULT_DISPLAY, null, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources2);
+
+        assertNotSame(resources1, resources2);
+        assertNotSame(resources1.getImpl(), resources2.getImpl());
+    }
+
+    @SmallTest
+    public void testUpdateConfigurationUpdatesAllAssetManagers() {
+        Resources resources1 = mResourcesManager.getResources(
+                null, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources1);
+
+        Resources resources2 = mResourcesManager.getResources(
+                null, APP_TWO_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources2);
+
+        Binder activity = new Binder();
+        final Configuration overrideConfig = new Configuration();
+        overrideConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
+        Resources resources3 = mResourcesManager.getResources(
+                activity, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY,
+                overrideConfig, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources3);
+
+        // No Resources object should be the same.
+        assertNotSame(resources1, resources2);
+        assertNotSame(resources1, resources3);
+        assertNotSame(resources2, resources3);
+
+        // Each ResourcesImpl should be different.
+        assertNotSame(resources1.getImpl(), resources2.getImpl());
+        assertNotSame(resources1.getImpl(), resources3.getImpl());
+        assertNotSame(resources2.getImpl(), resources3.getImpl());
+
+        Configuration newConfig = new Configuration();
+        newConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
+        mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null);
+
+        final Configuration expectedConfig = new Configuration();
+        expectedConfig.setLocales(LocaleList.getAdjustedDefault());
+        expectedConfig.densityDpi = mDisplayMetrics.densityDpi;
+        expectedConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
+
+        assertEquals(expectedConfig, resources1.getConfiguration());
+        assertEquals(expectedConfig, resources2.getConfiguration());
+        assertEquals(expectedConfig, resources3.getConfiguration());
+    }
+
+    @SmallTest
+    public void testTwoActivitiesWithIdenticalParametersShareImpl() {
+        Binder activity1 = new Binder();
+        Resources resources1 = mResourcesManager.getResources(
+                activity1, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources1);
+
+        Binder activity2 = new Binder();
+        Resources resources2 = mResourcesManager.getResources(
+                activity2, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources1);
+
+        // The references themselves should be unique.
+        assertNotSame(resources1, resources2);
+
+        // The implementations should be the same.
+        assertSame(resources1.getImpl(), resources2.getImpl());
+
+        final Configuration overrideConfig = new Configuration();
+        overrideConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
+        Resources resources3 = mResourcesManager.getResources(
+                activity2, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY,
+                overrideConfig, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+
+        // Since we requested new resources for activity2, the resource should be the same
+        // as the one returned before for activity2.
+        assertSame(resources2, resources3);
+
+        // But the implementation has changed.
+        assertNotSame(resources1.getImpl(), resources2.getImpl());
+    }
+
+    @SmallTest
+    public void testThemesGetUpdatedWithNewImpl() {
+        Binder activity1 = new Binder();
+        Resources resources1 = mResourcesManager.getResources(
+                activity1, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY, null,
+                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources1);
+
+        Resources.Theme theme = resources1.newTheme();
+        assertSame(resources1, theme.getResources());
+        theme.applyStyle(android.R.style.Theme_NoTitleBar, false);
+
+        TypedValue value = new TypedValue();
+        assertTrue(theme.resolveAttribute(android.R.attr.windowNoTitle, value, true));
+        assertEquals(TypedValue.TYPE_INT_BOOLEAN, value.type);
+        assertTrue(value.data != 0);
+
+        final Configuration overrideConfig = new Configuration();
+        overrideConfig.orientation = Configuration.ORIENTATION_LANDSCAPE;
+        Resources resources2 = mResourcesManager.getResources(
+                activity1, APP_ONE_RES_DIR, null, null, null, Display.DEFAULT_DISPLAY,
+                overrideConfig, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+        assertNotNull(resources2);
+        assertSame(resources1, resources2);
+        assertSame(resources2, theme.getResources());
+
+        // Make sure we can still access the data.
+        assertTrue(theme.resolveAttribute(android.R.attr.windowNoTitle, value, true));
+        assertEquals(TypedValue.TYPE_INT_BOOLEAN, value.type);
+        assertTrue(value.data != 0);
+    }
+}
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index a723977..9074f8a 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java
@@ -17,8 +17,8 @@
 package android.net;
 
 import static android.net.NetworkStats.ROAMING_ALL;
-import static android.net.NetworkStats.ROAMING_DEFAULT;
-import static android.net.NetworkStats.ROAMING_ROAMING;
+import static android.net.NetworkStats.ROAMING_NO;
+import static android.net.NetworkStats.ROAMING_YES;
 import static android.net.NetworkStats.SET_DEFAULT;
 import static android.net.NetworkStats.SET_FOREGROUND;
 import static android.net.NetworkStats.SET_DBG_VPN_IN;
@@ -46,57 +46,57 @@
 
     public void testFindIndex() throws Exception {
         final NetworkStats stats = new NetworkStats(TEST_START, 4)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, 0L,
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, 0L,
                         0L, 10)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 1024L,
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 1024L,
                         8L, 11)
-                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L,
+                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L,
                         1024L, 8L, 12)
-                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 1024L, 8L,
+                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_YES, 1024L, 8L,
                         1024L, 8L, 12);
 
-        assertEquals(3, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING));
-        assertEquals(2, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT));
-        assertEquals(1, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT));
-        assertEquals(0, stats.findIndex(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT));
-        assertEquals(-1, stats.findIndex(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT));
+        assertEquals(3, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_YES));
+        assertEquals(2, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO));
+        assertEquals(1, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO));
+        assertEquals(0, stats.findIndex(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO));
+        assertEquals(-1, stats.findIndex(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, ROAMING_NO));
     }
 
     public void testFindIndexHinted() {
         final NetworkStats stats = new NetworkStats(TEST_START, 3)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, 0L,
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, 0L,
                         0L, 10)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 1024L,
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 1024L,
                         8L, 11)
-                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L,
+                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L,
                         1024L, 8L, 12)
-                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L,
+                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 1024L, 8L,
                         0L, 0L, 10)
-                .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 0L, 0L, 1024L,
+                .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 0L, 0L, 1024L,
                         8L, 11)
-                .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L,
+                .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L,
                         1024L, 8L, 12)
-                .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 1024L, 8L,
+                .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, ROAMING_YES, 1024L, 8L,
                         1024L, 8L, 12);
 
         // verify that we correctly find across regardless of hinting
         for (int hint = 0; hint < stats.size(); hint++) {
             assertEquals(0, stats.findIndexHinted(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE,
-                    ROAMING_DEFAULT, hint));
+                    ROAMING_NO, hint));
             assertEquals(1, stats.findIndexHinted(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE,
-                    ROAMING_DEFAULT, hint));
+                    ROAMING_NO, hint));
             assertEquals(2, stats.findIndexHinted(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE,
-                    ROAMING_DEFAULT, hint));
+                    ROAMING_NO, hint));
             assertEquals(3, stats.findIndexHinted(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE,
-                    ROAMING_DEFAULT, hint));
+                    ROAMING_NO, hint));
             assertEquals(4, stats.findIndexHinted(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D,
-                    ROAMING_DEFAULT, hint));
+                    ROAMING_NO, hint));
             assertEquals(5, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE,
-                    ROAMING_DEFAULT, hint));
+                    ROAMING_NO, hint));
             assertEquals(6, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE,
-                    ROAMING_ROAMING, hint));
+                    ROAMING_YES, hint));
             assertEquals(-1, stats.findIndexHinted(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE,
-                    ROAMING_DEFAULT, hint));
+                    ROAMING_NO, hint));
         }
     }
 
@@ -106,41 +106,41 @@
         assertEquals(0, stats.size());
         assertEquals(3, stats.internalSize());
 
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1L, 1L, 2L,
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L, 1L, 2L,
                 2L, 3);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 2L, 2L, 2L,
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 2L, 2L, 2L,
                 2L, 4);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 3L, 3L, 2L,
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 3L, 3L, 2L,
                 2L, 5);
 
         assertEquals(3, stats.size());
         assertEquals(3, stats.internalSize());
 
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 4L, 40L, 4L,
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 4L, 40L, 4L,
                 40L, 7);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 5L, 50L, 4L,
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 5L, 50L, 4L,
                 40L, 8);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 6L, 60L, 5L,
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 6L, 60L, 5L,
                 50L, 10);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 7L, 70L, 5L,
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 7L, 70L, 5L,
                 50L, 11);
 
         assertEquals(7, stats.size());
         assertTrue(stats.internalSize() >= 7);
 
-        assertValues(stats, 0, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1L, 1L,
+        assertValues(stats, 0, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L, 1L,
                 2L, 2L, 3);
-        assertValues(stats, 1, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 2L, 2L,
+        assertValues(stats, 1, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 2L, 2L,
                 2L, 2L, 4);
-        assertValues(stats, 2, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 3L, 3L,
+        assertValues(stats, 2, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 3L, 3L,
                 2L, 2L, 5);
-        assertValues(stats, 3, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 4L,
+        assertValues(stats, 3, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 4L,
                 40L, 4L, 40L, 7);
-        assertValues(stats, 4, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 5L,
+        assertValues(stats, 4, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 5L,
                 50L, 4L, 40L, 8);
-        assertValues(stats, 5, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 6L,
+        assertValues(stats, 5, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 6L,
                 60L, 5L, 50L, 10);
-        assertValues(stats, 6, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 7L,
+        assertValues(stats, 6, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 7L,
                 70L, 5L, 50L, 11);
     }
 
@@ -152,19 +152,19 @@
         stats.combineValues(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, -128L, -1L,
                 -128L, -1L, -1);
 
-        assertValues(stats, 0, TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 384L, 3L,
+        assertValues(stats, 0, TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, ROAMING_NO, 384L, 3L,
                 128L, 1L, 9);
-        assertValues(stats, 1, TEST_IFACE, 1001, SET_DEFAULT, 0xff, ROAMING_DEFAULT, 128L, 1L, 128L,
+        assertValues(stats, 1, TEST_IFACE, 1001, SET_DEFAULT, 0xff, ROAMING_NO, 128L, 1L, 128L,
                 1L, 2);
 
         // now try combining that should create row
         stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L,
                 128L, 1L, 3);
-        assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 1L,
+        assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 1L,
                 128L, 1L, 3);
         stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L,
                 128L, 1L, 3);
-        assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 256L, 2L,
+        assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, ROAMING_NO, 256L, 2L,
                 256L, 2L, 6);
     }
 
@@ -180,9 +180,9 @@
         final NetworkStats result = after.subtract(before);
 
         // identical data should result in zero delta
-        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 0L,
+        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L,
                 0L, 0);
-        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 0L,
+        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L,
                 0L, 0);
     }
 
@@ -198,9 +198,9 @@
         final NetworkStats result = after.subtract(before);
 
         // expect delta between measurements
-        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1L, 1L, 2L,
+        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L, 1L, 2L,
                 1L, 4);
-        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 3L, 1L, 4L,
+        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 3L, 1L, 4L,
                 1L, 8);
     }
 
@@ -217,11 +217,11 @@
         final NetworkStats result = after.subtract(before);
 
         // its okay to have new rows
-        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 0L,
+        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L,
                 0L, 0);
-        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 0L,
+        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L,
                 0L, 0);
-        assertValues(result, 2, TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L,
+        assertValues(result, 2, TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L,
                 1024L, 8L, 20);
     }
 
@@ -237,7 +237,7 @@
 
         // should silently drop omitted rows
         assertEquals(1, result.size());
-        assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1L,
+        assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L,
                 2L, 3L, 4L, 0);
         assertEquals(4L, result.getTotalBytes());
     }
@@ -264,11 +264,11 @@
         assertEquals(64L, uidTag.getTotalBytes());
 
         final NetworkStats uidRoaming = new NetworkStats(TEST_START, 3)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L, 0L,
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L,
                         0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L, 0L,
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L,
                         0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 32L, 0L, 0L, 0L,
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_YES, 32L, 0L, 0L, 0L,
                         0L);
         assertEquals(96L, uidRoaming.getTotalBytes());
     }
@@ -283,11 +283,11 @@
 
     public void testGroupedByIfaceAll() throws Exception {
         final NetworkStats uidStats = new NetworkStats(TEST_START, 3)
-                .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L, 2L,
+                .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, 2L,
                         20L)
-                .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L,
+                .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 128L, 8L, 0L,
                         2L, 20L)
-                .addValues(IFACE_ALL, 101, SET_ALL, TAG_NONE, ROAMING_ROAMING, 128L, 8L, 0L, 2L,
+                .addValues(IFACE_ALL, 101, SET_ALL, TAG_NONE, ROAMING_YES, 128L, 8L, 0L, 2L,
                         20L);
         final NetworkStats grouped = uidStats.groupedByIface();
 
@@ -300,19 +300,19 @@
 
     public void testGroupedByIface() throws Exception {
         final NetworkStats uidStats = new NetworkStats(TEST_START, 7)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L,
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L,
                         2L, 20L)
-                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 512L, 32L, 0L,
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 512L, 32L, 0L,
                         0L, 0L)
-                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 64L, 4L, 0L, 0L,
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 4L, 0L, 0L,
                         0L)
-                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 512L, 32L,
+                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 512L, 32L,
                         0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L,
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L,
                         0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 128L, 8L, 0L, 0L,
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 128L, 8L, 0L, 0L,
                         0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 128L, 8L, 0L,
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 8L, 0L,
                         0L, 0L);
 
         final NetworkStats grouped = uidStats.groupedByIface();
@@ -328,49 +328,49 @@
 
     public void testAddAllValues() {
         final NetworkStats first = new NetworkStats(TEST_START, 5)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L, 0L,
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L,
                         0L)
-                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L,
+                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 32L, 0L, 0L,
                         0L, 0L)
-                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_ROAMING, 32L, 0L, 0L,
+                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_YES, 32L, 0L, 0L,
                         0L, 0L);
 
         final NetworkStats second = new NetworkStats(TEST_START, 2)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L, 0L,
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L,
                         0L)
-                .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L,
+                .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L,
                         0L, 0L, 0L)
-                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_ROAMING, 32L, 0L, 0L,
+                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_YES, 32L, 0L, 0L,
                         0L, 0L);
 
         first.combineAllValues(second);
 
         assertEquals(4, first.size());
-        assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 64L, 0L, 0L,
+        assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 64L, 0L, 0L,
                 0L, 0L);
-        assertValues(first, 1, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 32L, 0L,
+        assertValues(first, 1, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 32L, 0L,
                 0L, 0L, 0L);
-        assertValues(first, 2, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_ROAMING, 64L, 0L,
+        assertValues(first, 2, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_YES, 64L, 0L,
                 0L, 0L, 0L);
-        assertValues(first, 3, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L,
+        assertValues(first, 3, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L,
                 0L, 0L, 0L, 0L);
     }
 
     public void testGetTotal() {
         final NetworkStats stats = new NetworkStats(TEST_START, 7)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L,
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L,
                         2L, 20L)
-                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 512L, 32L, 0L,
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 512L, 32L, 0L,
                         0L, 0L)
-                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 64L, 4L, 0L, 0L,
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 4L, 0L, 0L,
                         0L)
-                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 512L, 32L,
+                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 512L, 32L,
                         0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L,
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L,
                         0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 128L, 8L, 0L, 0L,
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 128L, 8L, 0L, 0L,
                         0L)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 128L, 8L, 0L,
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 8L, 0L,
                         0L, 0L);
 
         assertValues(stats.getTotal(null), 1408L, 88L, 0L, 2L, 20L);
@@ -396,9 +396,9 @@
         final NetworkStats after = before.withoutUids(new int[] { 100 });
         assertEquals(6, before.size());
         assertEquals(2, after.size());
-        assertValues(after, 0, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L,
+        assertValues(after, 0, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L,
                 0L, 0L, 0L);
-        assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 128L, 8L, 0L,
+        assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 128L, 8L, 0L,
                 0L, 0L);
     }
 
@@ -457,53 +457,53 @@
         assertEquals(21, delta.size());
 
         // tunIface and TEST_IFACE entries are not changed.
-        assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+        assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                 39605L, 46L, 12259L, 55L, 0L);
-        assertValues(delta, 1, tunIface, 10100, SET_FOREGROUND, TAG_NONE,  ROAMING_DEFAULT, 0L, 0L,
+        assertValues(delta, 1, tunIface, 10100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 0L, 0L,
                 0L, 0L, 0L);
-        assertValues(delta, 2, tunIface, 10120, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+        assertValues(delta, 2, tunIface, 10120, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                 72667L, 197L, 43909L, 241L, 0L);
-        assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT,
+        assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_NO,
                 9297L, 17L, 4128L, 21L, 0L);
-        assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+        assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                 4983L, 10L, 1801L, 12L, 0L);
-        assertValues(delta, 5, tunIface, tunUid, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 0L, 0L,
+        assertValues(delta, 5, tunIface, tunUid, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 0L, 0L,
                 0L, 0L, 0L);
-        assertValues(delta, 6, tunIface, 10120, SET_DEFAULT, testTag1, ROAMING_DEFAULT,
+        assertValues(delta, 6, tunIface, 10120, SET_DEFAULT, testTag1, ROAMING_NO,
                 21691L, 41L, 13820L, 51L, 0L);
-        assertValues(delta, 7, tunIface, 10120, SET_FOREGROUND, testTag1, ROAMING_DEFAULT, 1281L,
+        assertValues(delta, 7, tunIface, 10120, SET_FOREGROUND, testTag1, ROAMING_NO, 1281L,
                 2L, 665L, 2L, 0L);
-        assertValues(delta, 8, TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1685L, 5L,
+        assertValues(delta, 8, TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1685L, 5L,
                 2070L, 6L, 0L);
 
         // Existing underlying Iface entries are updated
-        assertValues(delta, 9, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+        assertValues(delta, 9, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                 44783L, 54L, 13829L, 60L, 0L);
-        assertValues(delta, 10, underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT,
+        assertValues(delta, 10, underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, ROAMING_NO,
                 0L, 0L, 0L, 0L, 0L);
 
         // VPN underlying Iface entries are updated
-        assertValues(delta, 11, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+        assertValues(delta, 11, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                 28304L, 27L, 1719L, 12L, 0L);
-        assertValues(delta, 12, underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT,
+        assertValues(delta, 12, underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, ROAMING_NO,
                 0L, 0L, 0L, 0L, 0L);
 
         // New entries are added for new application's underlying Iface traffic
-        assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+        assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                 72667L, 197L, 41872L, 219L, 0L);
-        assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT,
+        assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_NO,
                 9297L, 17L, 3936, 19L, 0L);
-        assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, ROAMING_DEFAULT,
+        assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, ROAMING_NO,
                 21691L, 41L, 13179L, 46L, 0L);
-        assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, ROAMING_DEFAULT,
+        assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, ROAMING_NO,
                 1281L, 2L, 634L, 1L, 0L);
 
         // New entries are added for debug purpose
-        assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, ROAMING_DEFAULT,
+        assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO,
                 39605L, 46L, 11690, 49, 0);
-        assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, ROAMING_DEFAULT,
+        assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO,
                 81964, 214, 45808, 238, 0);
-        assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_IN, TAG_NONE, ROAMING_DEFAULT,
+        assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO,
                 4983, 10, 1717, 10, 0);
         assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, ROAMING_ALL,
                 126552, 270, 59215, 297, 0);
diff --git a/core/tests/coretests/src/android/text/method/BackspaceTest.java b/core/tests/coretests/src/android/text/method/BackspaceTest.java
index d2e811c..3be9cfc 100644
--- a/core/tests/coretests/src/android/text/method/BackspaceTest.java
+++ b/core/tests/coretests/src/android/text/method/BackspaceTest.java
@@ -29,7 +29,8 @@
 /**
  * Test backspace key handling of {@link android.text.method.BaseKeyListner}.
  *
- * TODO: Move some of test cases to the CTS.
+ * Only contains edge cases. For normal cases, see {@see android.text.method.cts.BackspaceTest}.
+ * TODO: introduce test cases for surrogate pairs and replacement span.
  */
 public class BackspaceTest extends KeyListenerTestCase {
     private static final BaseKeyListener mKeyListener = new BaseKeyListener() {
@@ -65,85 +66,9 @@
     }
 
     @SmallTest
-    public void testSurrogatePairs() {
-        EditorState state = new EditorState();
-
-        state.setByString("U+1F441 |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        state.setByString("U+1F441 U+1F5E8 |");
-        backspace(state, 0);
-        state.assertEquals("U+1F441 |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        // TODO: introduce edge cases.
-    }
-
-    @SmallTest
-    public void testReplacementSpan() {
-        EditorState state = new EditorState();
-
-        // ReplacementSpan will be set to "()" region.
-        state.setByString("'abc' ( 'de' ) 'fg' |");
-        backspace(state, 0);
-        state.assertEquals("'abc' ( 'de' ) 'f' |");
-        backspace(state, 0);
-        state.assertEquals("'abc' ( 'de' ) |");
-        backspace(state, 0);
-        state.assertEquals("'abc' |");
-        backspace(state, 0);
-        state.assertEquals("'ab' |");
-        backspace(state, 0);
-        state.assertEquals("'a' |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        state.setByString("'abc' [ ( 'de' ) ] 'fg'");
-        backspace(state, 0);
-        state.assertEquals("'abc' | 'fg'");
-        backspace(state, 0);
-        state.assertEquals("'ab' | 'fg'");
-        backspace(state, 0);
-        state.assertEquals("'a' | 'fg'");
-        backspace(state, 0);
-        state.assertEquals("| 'fg'");
-        backspace(state, 0);
-        state.assertEquals("| 'fg'");
-
-        state.setByString("'ab' [ 'c' ( 'de' ) 'f' ] 'g'");
-        backspace(state, 0);
-        state.assertEquals("'ab' | 'g'");
-        backspace(state, 0);
-        state.assertEquals("'a' | 'g'");
-        backspace(state, 0);
-        state.assertEquals("| 'g'");
-        backspace(state, 0);
-        state.assertEquals("| 'g'");
-
-        // TODO: introduce edge cases.
-    }
-
-    @SmallTest
     public void testCombiningEnclosingKeycaps() {
         EditorState state = new EditorState();
 
-        // U+20E3 is COMBINING ENCLOSING KEYCAP.
-        state.setByString("'1' U+20E3 |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        // Variation selector before COMBINING ECLOSING KEYCAP
-        state.setByString("'1' U+FE0E U+20E3 |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        state.setByString("'1' U+E0101 U+20E3 |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        // Edge cases
         // multiple COMBINING ENCLOSING KEYCAP
         state.setByString("'1' U+20E3 U+20E3 |");
         backspace(state, 0);
@@ -168,17 +93,6 @@
     public void testVariationSelector() {
         EditorState state = new EditorState();
 
-        // U+FE0F is VARIATION SELECTOR-16.
-        state.setByString("'#' U+FE0F |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        // U+E0100 is VARIATION SELECTOR-17.
-        state.setByString("U+845B U+E0100 |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        // Edge cases
         // Isolated variation selector
         state.setByString("U+FE0F |");
         backspace(state, 0);
@@ -243,20 +157,6 @@
     public void testEmojiZWJSequence() {
         EditorState state = new EditorState();
 
-        // U+200D is ZERO WIDTH JOINER.
-        state.setByString("U+1F441 U+200D U+1F5E8 |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        state.setByString("U+1F441 U+200D U+1F5E8 U+FE0E |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        state.setByString("U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468 |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        // Edge cases
         // End with ZERO WIDTH JOINER
         state.setByString("U+1F441 U+200D |");
         backspace(state, 0);
@@ -307,35 +207,6 @@
     public void testFlags() {
         EditorState state = new EditorState();
 
-        // U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U.
-        // U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S.
-        state.setByString("U+1F1FA U+1F1F8 |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        state.setByString("'a' U+1F1FA U+1F1F8 |");
-        backspace(state, 0);
-        state.assertEquals("'a' |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        state.setByString("U+1F1FA U+1F1F8 U+1F1FA U+1F1F8 |");
-        backspace(state, 0);
-        state.assertEquals("U+1F1FA U+1F1F8 |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        state.setByString("'a' U+1F1FA U+1F1F8 'b' U+1F1FA U+1F1F8 |");
-        backspace(state, 0);
-        state.assertEquals("'a' U+1F1FA U+1F1F8 'b' |");
-        backspace(state, 0);
-        state.assertEquals("'a' U+1F1FA U+1F1F8 |");
-        backspace(state, 0);
-        state.assertEquals("'a' |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        // Edcae cases
         // Isolated regional indicator symbol
         state.setByString("U+1F1FA |");
         backspace(state, 0);
@@ -353,12 +224,6 @@
     public void testEmojiModifier() {
         EditorState state = new EditorState();
 
-        // U+1F3FB is EMOJI MODIFIER FITZPATRICK TYPE-1-2.
-        state.setByString("U+1F466 U+1F3FB |");
-        backspace(state, 0);
-        state.assertEquals("|");
-
-        // Edge cases
         // Isolated emoji modifier
         state.setByString("U+1F3FB |");
         backspace(state, 0);
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
index da17045..f7dab2d 100644
--- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -29,7 +29,8 @@
 /**
  * Test forward delete key handling of  {@link android.text.method.BaseKeyListener}.
  *
- * TODO: Move some of test cases to the CTS.
+ * Only contains edge cases. For normal cases, see {@see android.text.method.cts.ForwardDeleteTest}.
+ * TODO: introduce test cases for surrogate pairs and replacement span.
  */
 public class ForwardDeleteTest extends KeyListenerTestCase {
     private static final BaseKeyListener mKeyListener = new BaseKeyListener() {
@@ -65,73 +66,9 @@
     }
 
     @SmallTest
-    public void testSurrogatePairs() {
-        EditorState state = new EditorState();
-
-        // U+1F441 is EYE
-        state.setByString("| U+1F441");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
-        // U+1F5E8 is LEFT SPEECH BUBBLE
-        state.setByString("| U+1F441 U+1F5E8");
-        forwardDelete(state, 0);
-        state.assertEquals("| U+1F5E8");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
-        // TODO: introduce edge cases.
-    }
-
-    @SmallTest
-    public void testReplacementSpan() {
-        EditorState state = new EditorState();
-
-        state.setByString("| 'abc' ( 'de' ) 'fg'");
-        forwardDelete(state, 0);
-        state.assertEquals("| 'bc' ( 'de' ) 'fg'");
-        forwardDelete(state, 0);
-        state.assertEquals("| 'c' ( 'de' ) 'fg'");
-        forwardDelete(state, 0);
-        state.assertEquals("| ( 'de' ) 'fg'");
-        forwardDelete(state, 0);
-        state.assertEquals("| 'fg'");
-        forwardDelete(state, 0);
-        state.assertEquals("| 'g'");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
-        state.setByString("'abc' [ ( 'de' ) ] 'fg'");
-        forwardDelete(state, 0);
-        state.assertEquals("'abc' | 'fg'");
-        forwardDelete(state, 0);
-        state.assertEquals("'abc' | 'g'");
-        forwardDelete(state, 0);
-        state.assertEquals("'abc' |");
-        forwardDelete(state, 0);
-        state.assertEquals("'abc' |");
-
-        state.setByString("'ab' [ 'c' ( 'de' ) 'f' ] 'g'");
-        forwardDelete(state, 0);
-        state.assertEquals("'ab' | 'g'");
-        forwardDelete(state, 0);
-        state.assertEquals("'ab' |");
-        forwardDelete(state, 0);
-        state.assertEquals("'ab' |");
-
-        // TODO: introduce edge cases.
-    }
-
-    @SmallTest
     public void testCombiningEnclosingKeycaps() {
         EditorState state = new EditorState();
 
-        // U+20E3 is COMBINING ENCLOSING KEYCAP.
-        state.setByString("| '1' U+20E3");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
-        // Edge cases
         // multiple COMBINING ENCLOSING KEYCAP
         state.setByString("| '1' U+20E3 U+20E3");
         forwardDelete(state, 0);
@@ -152,17 +89,6 @@
     public void testVariationSelector() {
         EditorState state = new EditorState();
 
-        // U+FE0F is VARIATION SELECTOR-16.
-        state.setByString("| '#' U+FE0F");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
-        // U+E0100 is VARIATION SELECTOR-17.
-        state.setByString("| U+845B U+E0100");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
-        // Edge cases
         // Isolated variation selectors
         state.setByString("| U+FE0F");
         forwardDelete(state, 0);
@@ -211,16 +137,6 @@
     public void testEmojiZeroWidthJoinerSequence() {
         EditorState state = new EditorState();
 
-        // U+200D is ZERO WIDTH JOINER.
-        state.setByString("| U+1F441 U+200D U+1F5E8");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
-        state.setByString("| U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
-        // Edge cases
         // End with ZERO WIDTH JOINER
         state.setByString("| U+1F441 U+200D");
         forwardDelete(state, 0);
@@ -255,19 +171,6 @@
     public void testFlags() {
         EditorState state = new EditorState();
 
-        // U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U.
-        // U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S.
-        state.setByString("| U+1F1FA U+1F1F8");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
-        state.setByString("| U+1F1FA U+1F1F8 U+1F1FA U+1F1F8");
-        forwardDelete(state, 0);
-        state.assertEquals("| U+1F1FA U+1F1F8");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
-        // Edge cases
         // Isolated regional indicator symbol
         state.setByString("| U+1F1FA");
         forwardDelete(state, 0);
@@ -285,12 +188,6 @@
     public void testEmojiModifier() {
         EditorState state = new EditorState();
 
-        // U+1F3FB is EMOJI MODIFIER FITZPATRICK TYPE-1-2.
-        state.setByString("| U+1F466 U+1F3FB");
-        forwardDelete(state, 0);
-        state.assertEquals("|");
-
-        // Edge cases
         // Isolated emoji modifier
         state.setByString("| U+1F3FB");
         forwardDelete(state, 0);
diff --git a/core/tests/coretests/src/android/transition/AutoTransitionTest.java b/core/tests/coretests/src/android/transition/AutoTransitionTest.java
new file mode 100644
index 0000000..834fb7a
--- /dev/null
+++ b/core/tests/coretests/src/android/transition/AutoTransitionTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.transition;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(AndroidJUnit4.class)
+public class AutoTransitionTest {
+    @Test
+    @SmallTest
+    public void testFadeOutMoveFadeIn() throws Throwable {
+        AutoTransition autoTransition = new AutoTransition();
+        assertEquals(3, autoTransition.getTransitionCount());
+        Transition fadeOut = autoTransition.getTransitionAt(0);
+        assertNotNull(fadeOut);
+        assertTrue(fadeOut instanceof Fade);
+        assertEquals(Visibility.MODE_OUT, ((Fade)fadeOut).getMode());
+
+        Transition move = autoTransition.getTransitionAt(1);
+        assertNotNull(move);
+        assertTrue(move instanceof ChangeBounds);
+
+        Transition fadeIn = autoTransition.getTransitionAt(2);
+        assertNotNull(fadeIn);
+        assertTrue(fadeIn instanceof Fade);
+        assertEquals(Visibility.MODE_IN, ((Fade)fadeIn).getMode());
+
+        assertEquals(TransitionSet.ORDERING_SEQUENTIAL, autoTransition.getOrdering());
+    }
+}
diff --git a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
index 3d8fe69..a37abf1 100644
--- a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
+++ b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
@@ -32,6 +32,8 @@
 
 /**
  * SuggestionsPopupWindowTest tests.
+ *
+ * TODO: Add tests for when there are no suggestions
  */
 public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2<TextViewActivity> {
 
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
index 00df87d..923b829 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
@@ -143,6 +143,8 @@
 
         onView(withId(R.id.textview)).check(hasSelection(""));
         onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("i")));
+
+        // TODO: Add tests for suggestions
     }
 
     @SmallTest
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 844eadb..4a4727f 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -47,6 +47,8 @@
 import android.support.test.espresso.action.EspressoKey;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.text.Selection;
+import android.text.Spannable;
 import android.view.KeyEvent;
 
 import static org.hamcrest.Matchers.anyOf;
@@ -534,4 +536,68 @@
                 .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('i')));
         onView(withId(R.id.textview)).check(hasSelection("hijk"));
     }
+
+    @SmallTest
+    public void testSetSelectionAndActionMode() throws Exception {
+        final String text = "abc def";
+        onView(withId(R.id.textview)).perform(click());
+        onView(withId(R.id.textview)).perform(replaceText(text));
+
+        final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+        assertFloatingToolbarIsNotDisplayed();
+        textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0, 3));
+        getInstrumentation().waitForIdleSync();
+        sleepForFloatingToolbarPopup();
+        // Don't automatically start action mode.
+        assertFloatingToolbarIsNotDisplayed();
+        // Make sure that "Select All" is included in the selection action mode when the entire text
+        // is not selected.
+        onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('e')));
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+        // Changing the selection range by API should not interrupt the selection action mode.
+        textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0, 3));
+        getInstrumentation().waitForIdleSync();
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+        assertFloatingToolbarContainsItem(
+                getActivity().getString(com.android.internal.R.string.selectAll));
+        // Make sure that "Select All" is no longer included when the entire text is selected by
+        // API.
+        textView.post(
+                () -> Selection.setSelection((Spannable) textView.getText(), 0, text.length()));
+        getInstrumentation().waitForIdleSync();
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+        assertFloatingToolbarDoesNotContainItem(
+                getActivity().getString(com.android.internal.R.string.selectAll));
+        // Make sure that shrinking the selection range to cursor (an empty range) by API
+        // terminates selection action mode and does not trigger the insertion action mode.
+        textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0));
+        getInstrumentation().waitForIdleSync();
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsNotDisplayed();
+        // Make sure that user click can trigger the insertion action mode.
+        onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length()));
+        onHandleView(com.android.internal.R.id.insertion_handle).perform(click());
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+        // Make sure that an existing insertion action mode keeps alive after the insertion point is
+        // moved by API.
+        textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0));
+        getInstrumentation().waitForIdleSync();
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+        assertFloatingToolbarDoesNotContainItem(
+                getActivity().getString(com.android.internal.R.string.copy));
+        // Make sure that selection action mode is started after selection is created by API when
+        // insertion action mode is active.
+        textView.post(
+                () -> Selection.setSelection((Spannable) textView.getText(), 1, text.length()));
+        getInstrumentation().waitForIdleSync();
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarIsDisplayed();
+        assertFloatingToolbarContainsItem(
+                getActivity().getString(com.android.internal.R.string.copy));
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
index 719b274..6b5e4ad 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
@@ -219,9 +219,28 @@
         final InputMethodSubtype nonAutoHi = createDummyInputMethodSubtype("hi",
                 SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
                 !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+        final InputMethodSubtype nonAutoSrCyrl = createDummyInputMethodSubtype("sr",
+                "sr-Cyrl", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+                !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+                !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+        final InputMethodSubtype nonAutoSrLatn = createDummyInputMethodSubtype("sr_ZZ",
+                "sr-Latn", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+                !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
+                !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
         final InputMethodSubtype nonAutoHandwritingEn = createDummyInputMethodSubtype("en",
                 SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
                 !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+        final InputMethodSubtype nonAutoHandwritingFr = createDummyInputMethodSubtype("fr",
+                SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+                !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+        final InputMethodSubtype nonAutoHandwritingSrCyrl = createDummyInputMethodSubtype("sr",
+                "sr-Cyrl", SUBTYPE_MODE_HANDWRITING, !IS_AUX,
+                !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+                !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+        final InputMethodSubtype nonAutoHandwritingSrLatn = createDummyInputMethodSubtype("sr_ZZ",
+                "sr-Latn", SUBTYPE_MODE_HANDWRITING, !IS_AUX,
+                !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
+                !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
         final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype =
                 createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
                         !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
@@ -242,6 +261,8 @@
             subtypes.add(autoSubtype);  // overridesImplicitlyEnabledSubtype == true
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             final InputMethodInfo imi = createDummyInputMethodInfo(
                     "com.android.apps.inputmethod.latin",
                     "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
@@ -264,6 +285,8 @@
             subtypes.add(nonAutoFil);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             final InputMethodInfo imi = createDummyInputMethodInfo(
                     "com.android.apps.inputmethod.latin",
                     "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
@@ -271,7 +294,9 @@
             final ArrayList<InputMethodSubtype> result =
                     InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
                             getResourcesForLocales(LOCALE_EN_US), imi);
+            assertEquals(2, result.size());
             verifyEquality(nonAutoEnUS, result.get(0));
+            verifyEquality(nonAutoHandwritingEn, result.get(1));
         }
 
         // Make sure that a subtype whose locale is exactly equal to the specified locale is
@@ -284,6 +309,8 @@
             subtypes.add(nonAutoJa);
             subtypes.add(nonAutoFil);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             final InputMethodInfo imi = createDummyInputMethodInfo(
                     "com.android.apps.inputmethod.latin",
                     "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
@@ -291,8 +318,9 @@
             final ArrayList<InputMethodSubtype> result =
                     InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
                             getResourcesForLocales(LOCALE_EN_GB), imi);
-            assertEquals(1, result.size());
+            assertEquals(2, result.size());
             verifyEquality(nonAutoEnGB, result.get(0));
+            verifyEquality(nonAutoHandwritingEn, result.get(1));
         }
 
         // If there is no automatic subtype (overridesImplicitlyEnabledSubtype:true) and
@@ -306,6 +334,8 @@
             subtypes.add(nonAutoFil);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             final InputMethodInfo imi = createDummyInputMethodInfo(
                     "com.android.apps.inputmethod.latin",
                     "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
@@ -313,8 +343,9 @@
             final ArrayList<InputMethodSubtype> result =
                     InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
                             getResourcesForLocales(LOCALE_FR), imi);
-            assertEquals(1, result.size());
+            assertEquals(2, result.size());
             verifyEquality(nonAutoFrCA, result.get(0));
+            verifyEquality(nonAutoHandwritingFr, result.get(1));
         }
         // Then make sure that a subtype (locale: "fr") can be found with locale: "fr_CA".
         {
@@ -324,6 +355,8 @@
             subtypes.add(nonAutoFil);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             final InputMethodInfo imi = createDummyInputMethodInfo(
                     "com.android.apps.inputmethod.latin",
                     "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
@@ -331,8 +364,9 @@
             final ArrayList<InputMethodSubtype> result =
                     InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
                             getResourcesForLocales(LOCALE_FR_CA), imi);
-            assertEquals(1, result.size());
+            assertEquals(2, result.size());
             verifyEquality(nonAutoFrCA, result.get(0));
+            verifyEquality(nonAutoHandwritingFr, result.get(1));
         }
 
         // Make sure that subtypes which have "EnabledWhenDefaultIsNotAsciiCapable" in its
@@ -343,6 +377,8 @@
             subtypes.add(nonAutoJa);    // not ASCII capable
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             final InputMethodInfo imi = createDummyInputMethodInfo(
                     "com.android.apps.inputmethod.latin",
                     "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
@@ -363,6 +399,7 @@
             subtypes.add(nonAutoHi);
             subtypes.add(nonAutoEnUS);
             subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
             final InputMethodInfo imi = createDummyInputMethodInfo(
                     "com.android.apps.inputmethod.latin",
@@ -379,6 +416,7 @@
             subtypes.add(nonAutoEnUS);
             subtypes.add(nonAutoHi);
             subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
             final InputMethodInfo imi = createDummyInputMethodInfo(
                     "com.android.apps.inputmethod.latin",
@@ -393,6 +431,7 @@
         {
             final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
             subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
             subtypes.add(nonAutoEnUS);
             subtypes.add(nonAutoHi);
             subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
@@ -407,6 +446,85 @@
             verifyEquality(nonAutoEnUS, result.get(0));
         }
 
+        // Make sure that both language and script are taken into account to find the best matching
+        // subtype.
+        {
+            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+            subtypes.add(nonAutoEnUS);
+            subtypes.add(nonAutoSrCyrl);
+            subtypes.add(nonAutoSrLatn);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
+            subtypes.add(nonAutoHandwritingSrCyrl);
+            subtypes.add(nonAutoHandwritingSrLatn);
+            final InputMethodInfo imi = createDummyInputMethodInfo(
+                    "com.android.apps.inputmethod.latin",
+                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+                    subtypes);
+            final ArrayList<InputMethodSubtype> result =
+                    InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+                            getResourcesForLocales(Locale.forLanguageTag("sr-Latn-RS")), imi);
+            assertEquals(2, result.size());
+            assertThat(nonAutoSrLatn, isIn(result));
+            assertThat(nonAutoHandwritingSrLatn, isIn(result));
+        }
+        {
+            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+            subtypes.add(nonAutoEnUS);
+            subtypes.add(nonAutoSrCyrl);
+            subtypes.add(nonAutoSrLatn);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
+            subtypes.add(nonAutoHandwritingSrCyrl);
+            subtypes.add(nonAutoHandwritingSrLatn);
+            final InputMethodInfo imi = createDummyInputMethodInfo(
+                    "com.android.apps.inputmethod.latin",
+                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+                    subtypes);
+            final ArrayList<InputMethodSubtype> result =
+                    InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+                            getResourcesForLocales(Locale.forLanguageTag("sr-Cyrl-RS")), imi);
+            assertEquals(2, result.size());
+            assertThat(nonAutoSrCyrl, isIn(result));
+            assertThat(nonAutoHandwritingSrCyrl, isIn(result));
+        }
+
+        // Make sure that secondary locales are taken into account to find the best matching
+        // subtype.
+        {
+            final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+            subtypes.add(nonAutoEnUS);
+            subtypes.add(nonAutoEnGB);
+            subtypes.add(nonAutoSrCyrl);
+            subtypes.add(nonAutoSrLatn);
+            subtypes.add(nonAutoFr);
+            subtypes.add(nonAutoFrCA);
+            subtypes.add(nonAutoHandwritingEn);
+            subtypes.add(nonAutoHandwritingFr);
+            subtypes.add(nonAutoHandwritingSrCyrl);
+            subtypes.add(nonAutoHandwritingSrLatn);
+            final InputMethodInfo imi = createDummyInputMethodInfo(
+                    "com.android.apps.inputmethod.latin",
+                    "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+                    subtypes);
+            final ArrayList<InputMethodSubtype> result =
+                    InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+                            getResourcesForLocales(
+                                    Locale.forLanguageTag("sr-Latn-RS-x-android"),
+                                    Locale.forLanguageTag("ja-JP"),
+                                    Locale.forLanguageTag("fr-FR"),
+                                    Locale.forLanguageTag("en-GB"),
+                                    Locale.forLanguageTag("en-US")),
+                            imi);
+            assertEquals(6, result.size());
+            assertThat(nonAutoEnGB, isIn(result));
+            assertThat(nonAutoFr, isIn(result));
+            assertThat(nonAutoSrLatn, isIn(result));
+            assertThat(nonAutoHandwritingEn, isIn(result));
+            assertThat(nonAutoHandwritingFr, isIn(result));
+            assertThat(nonAutoHandwritingSrLatn, isIn(result));
+        }
+
         // Make sure that 3-letter language code can be handled.
         {
             final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
@@ -755,7 +873,15 @@
     private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode,
             boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype,
             boolean isAsciiCapable, boolean isEnabledWhenDefaultIsNotAsciiCapable) {
+        return createDummyInputMethodSubtype(locale, null /* languageTag */, mode, isAuxiliary,
+                overridesImplicitlyEnabledSubtype, isAsciiCapable,
+                isEnabledWhenDefaultIsNotAsciiCapable);
+    }
 
+    private static InputMethodSubtype createDummyInputMethodSubtype(String locale,
+            String languageTag, String mode, boolean isAuxiliary,
+            boolean overridesImplicitlyEnabledSubtype, boolean isAsciiCapable,
+            boolean isEnabledWhenDefaultIsNotAsciiCapable) {
         final StringBuilder subtypeExtraValue = new StringBuilder();
         if (isEnabledWhenDefaultIsNotAsciiCapable) {
             subtypeExtraValue.append(EXTRA_VALUE_PAIR_SEPARATOR);
@@ -773,6 +899,7 @@
                 .setSubtypeNameResId(0)
                 .setSubtypeIconResId(0)
                 .setSubtypeLocale(locale)
+                .setLanguageTag(languageTag)
                 .setSubtypeMode(mode)
                 .setSubtypeExtraValue(subtypeExtraValue.toString())
                 .setIsAuxiliary(isAuxiliary)
diff --git a/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java b/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java
index 12a75b8..327f3fd 100644
--- a/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java
+++ b/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.net;
 
-import static android.net.NetworkStats.ROAMING_DEFAULT;
+import static android.net.NetworkStats.ROAMING_NO;
 import static android.net.NetworkStats.SET_ALL;
 import static android.net.NetworkStats.SET_DEFAULT;
 import static android.net.NetworkStats.SET_FOREGROUND;
@@ -157,7 +157,7 @@
 
     private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set,
             int tag, long rxBytes, long txBytes) {
-        final int i = stats.findIndex(iface, uid, set, tag, ROAMING_DEFAULT);
+        final int i = stats.findIndex(iface, uid, set, tag, ROAMING_NO);
         final NetworkStats.Entry entry = stats.getValues(i, null);
         assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
         assertEquals("unexpected txBytes", txBytes, entry.txBytes);
@@ -165,7 +165,7 @@
 
     private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set,
             int tag, long rxBytes, long rxPackets, long txBytes, long txPackets) {
-        final int i = stats.findIndex(iface, uid, set, tag, ROAMING_DEFAULT);
+        final int i = stats.findIndex(iface, uid, set, tag, ROAMING_NO);
         final NetworkStats.Entry entry = stats.getValues(i, null);
         assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
         assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
diff --git a/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
new file mode 100644
index 0000000..b3897ce
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2016 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.util;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+public class ArrayUtilsTest extends TestCase {
+
+    @SmallTest
+    public void testUnstableRemoveIf() throws Exception {
+        java.util.function.Predicate<Object> isNull = new java.util.function.Predicate<Object>() {
+            @Override
+            public boolean test(Object o) {
+                return o == null;
+            }
+        };
+
+        final Object a = new Object();
+        final Object b = new Object();
+        final Object c = new Object();
+
+        ArrayList<Object> collection = null;
+        assertEquals(0, ArrayUtils.unstableRemoveIf(collection, isNull));
+
+        collection = new ArrayList<>();
+        assertEquals(0, ArrayUtils.unstableRemoveIf(collection, isNull));
+
+        collection = new ArrayList<>(Collections.singletonList(a));
+        assertEquals(0, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(1, collection.size());
+        assertTrue(collection.contains(a));
+
+        collection = new ArrayList<>(Collections.singletonList(null));
+        assertEquals(1, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(0, collection.size());
+
+        collection = new ArrayList<>(Arrays.asList(a, b));
+        assertEquals(0, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(2, collection.size());
+        assertTrue(collection.contains(a));
+        assertTrue(collection.contains(b));
+
+        collection = new ArrayList<>(Arrays.asList(a, null));
+        assertEquals(1, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(1, collection.size());
+        assertTrue(collection.contains(a));
+
+        collection = new ArrayList<>(Arrays.asList(null, a));
+        assertEquals(1, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(1, collection.size());
+        assertTrue(collection.contains(a));
+
+        collection = new ArrayList<>(Arrays.asList(null, null));
+        assertEquals(2, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(0, collection.size());
+
+        collection = new ArrayList<>(Arrays.asList(a, b, c));
+        assertEquals(0, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(3, collection.size());
+        assertTrue(collection.contains(a));
+        assertTrue(collection.contains(b));
+        assertTrue(collection.contains(c));
+
+        collection = new ArrayList<>(Arrays.asList(a, b, null));
+        assertEquals(1, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(2, collection.size());
+        assertTrue(collection.contains(a));
+        assertTrue(collection.contains(b));
+
+        collection = new ArrayList<>(Arrays.asList(a, null, b));
+        assertEquals(1, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(2, collection.size());
+        assertTrue(collection.contains(a));
+        assertTrue(collection.contains(b));
+
+        collection = new ArrayList<>(Arrays.asList(null, a, b));
+        assertEquals(1, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(2, collection.size());
+        assertTrue(collection.contains(a));
+        assertTrue(collection.contains(b));
+
+        collection = new ArrayList<>(Arrays.asList(a, null, null));
+        assertEquals(2, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(1, collection.size());
+        assertTrue(collection.contains(a));
+
+        collection = new ArrayList<>(Arrays.asList(null, null, a));
+        assertEquals(2, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(1, collection.size());
+        assertTrue(collection.contains(a));
+
+        collection = new ArrayList<>(Arrays.asList(null, a, null));
+        assertEquals(2, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(1, collection.size());
+        assertTrue(collection.contains(a));
+
+        collection = new ArrayList<>(Arrays.asList(null, null, null));
+        assertEquals(3, ArrayUtils.unstableRemoveIf(collection, isNull));
+        assertEquals(0, collection.size());
+    }
+}
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index de741b3..fd28f64 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -95,3 +95,14 @@
 
 build-one-font-module :=
 font_src_files :=
+
+
+# Run sanity tests on fonts on checkbuild
+checkbuild: fontchain_lint
+
+FONTCHAIN_LINTER := frameworks/base/tools/fonts/fontchain_lint.py
+
+.PHONY: fontchain_lint
+fontchain_lint: $(FONTCHAIN_LINTER) $(TARGET_OUT)/etc/fonts.xml
+	PYTHONPATH=$$PYTHONPATH:external/fonttools/Lib \
+	python $(FONTCHAIN_LINTER) $(TARGET_OUT) external/unicode
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index dc302c7..bcac6a1 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -88,242 +88,246 @@
     </family>
 
     <!-- fallback fonts -->
-    <family variant="elegant">
+    <family lang="und-Arab" variant="elegant">
         <font weight="400" style="normal">NotoNaskhArabic-Regular.ttf</font>
         <font weight="700" style="normal">NotoNaskhArabic-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Arab" variant="compact">
         <font weight="400" style="normal">NotoNaskhArabicUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoNaskhArabicUI-Bold.ttf</font>
     </family>
-    <family>
+    <family lang="und-Ethi">
         <font weight="400" style="normal">NotoSansEthiopic-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansEthiopic-Bold.ttf</font>
     </family>
-    <family>
+    <family lang="und-Hebr">
         <font weight="400" style="normal">NotoSansHebrew-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansHebrew-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Thai" variant="elegant">
         <font weight="400" style="normal">NotoSansThai-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansThai-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Thai" variant="compact">
         <font weight="400" style="normal">NotoSansThaiUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
     </family>
-    <family>
+    <family lang="und-Armn">
         <font weight="400" style="normal">NotoSansArmenian-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansArmenian-Bold.ttf</font>
     </family>
-    <family>
+    <!-- TODO: add Geok -->
+    <family lang="und-Geor">
         <font weight="400" style="normal">NotoSansGeorgian-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansGeorgian-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Deva" variant="elegant">
         <font weight="400" style="normal">NotoSansDevanagari-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansDevanagari-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Deva" variant="compact">
         <font weight="400" style="normal">NotoSansDevanagariUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansDevanagariUI-Bold.ttf</font>
     </family>
-    <!-- Gujarati should come after Devanagari -->
-    <family variant="elegant">
+
+    <!-- All scripts of India should come after Devanagari, due to shared
+         danda characters.
+    -->
+    <family lang="und-Gujr" variant="elegant">
         <font weight="400" style="normal">NotoSansGujarati-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Gujr" variant="compact">
         <font weight="400" style="normal">NotoSansGujaratiUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
     </family>
-    <!-- Gurmukhi should come after Devanagari -->
-    <family variant="elegant">
+    <family lang="und-Guru" variant="elegant">
         <font weight="400" style="normal">NotoSansGurmukhi-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansGurmukhi-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Guru" variant="compact">
         <font weight="400" style="normal">NotoSansGurmukhiUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansGurmukhiUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Taml" variant="elegant">
         <font weight="400" style="normal">NotoSansTamil-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansTamil-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Taml" variant="compact">
         <font weight="400" style="normal">NotoSansTamilUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansTamilUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Mlym" variant="elegant">
         <font weight="400" style="normal">NotoSansMalayalam-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansMalayalam-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Mlym" variant="compact">
         <font weight="400" style="normal">NotoSansMalayalamUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansMalayalamUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Beng" variant="elegant">
         <font weight="400" style="normal">NotoSansBengali-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansBengali-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Beng" variant="compact">
         <font weight="400" style="normal">NotoSansBengaliUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansBengaliUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Telu" variant="elegant">
         <font weight="400" style="normal">NotoSansTelugu-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansTelugu-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Telu" variant="compact">
         <font weight="400" style="normal">NotoSansTeluguUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansTeluguUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Knda" variant="elegant">
         <font weight="400" style="normal">NotoSansKannada-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansKannada-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Knda" variant="compact">
         <font weight="400" style="normal">NotoSansKannadaUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansKannadaUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Orya" variant="elegant">
         <font weight="400" style="normal">NotoSansOriya-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansOriya-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Orya" variant="compact">
         <font weight="400" style="normal">NotoSansOriyaUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
     </family>
-    <family>
+
+    <family lang="und-Sinh">
         <font weight="400" style="normal">NotoSansSinhala-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansSinhala-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Khmr" variant="elegant">
         <font weight="400" style="normal">NotoSansKhmer-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansKhmer-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Khmr" variant="compact">
         <font weight="400" style="normal">NotoSansKhmerUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansKhmerUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Laoo" variant="elegant">
         <font weight="400" style="normal">NotoSansLao-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansLao-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Laoo" variant="compact">
         <font weight="400" style="normal">NotoSansLaoUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
     </family>
-    <family variant="elegant">
+    <family lang="und-Mymr" variant="elegant">
         <font weight="400" style="normal">NotoSansMyanmar-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansMyanmar-Bold.ttf</font>
     </family>
-    <family variant="compact">
+    <family lang="und-Mymr" variant="compact">
         <font weight="400" style="normal">NotoSansMyanmarUI-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansMyanmarUI-Bold.ttf</font>
     </family>
-    <family>
+    <family lang="und-Thaa">
         <font weight="400" style="normal">NotoSansThaana-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansThaana-Bold.ttf</font>
     </family>
-    <family>
+    <family lang="und-Cham">
         <font weight="400" style="normal">NotoSansCham-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
     </family>
-    <family>
+    <family lang="und-Bali">
         <font weight="400" style="normal">NotoSansBalinese-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Bamu">
         <font weight="400" style="normal">NotoSansBamum-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Batk">
         <font weight="400" style="normal">NotoSansBatak-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Bugi">
         <font weight="400" style="normal">NotoSansBuginese-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Buhd">
         <font weight="400" style="normal">NotoSansBuhid-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Cans">
         <font weight="400" style="normal">NotoSansCanadianAboriginal-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Cher">
         <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Copt">
         <font weight="400" style="normal">NotoSansCoptic-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Glag">
         <font weight="400" style="normal">NotoSansGlagolitic-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Hano">
         <font weight="400" style="normal">NotoSansHanunoo-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Java">
         <font weight="400" style="normal">NotoSansJavanese-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Kali">
         <font weight="400" style="normal">NotoSansKayahLi-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Lepc">
         <font weight="400" style="normal">NotoSansLepcha-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Limb">
         <font weight="400" style="normal">NotoSansLimbu-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Lisu">
         <font weight="400" style="normal">NotoSansLisu-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Mand">
         <font weight="400" style="normal">NotoSansMandaic-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Mtei">
         <font weight="400" style="normal">NotoSansMeeteiMayek-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Talu">
         <font weight="400" style="normal">NotoSansNewTaiLue-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Nkoo">
         <font weight="400" style="normal">NotoSansNKo-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Olck">
         <font weight="400" style="normal">NotoSansOlChiki-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Rjng">
         <font weight="400" style="normal">NotoSansRejang-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Saur">
         <font weight="400" style="normal">NotoSansSaurashtra-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Sund">
         <font weight="400" style="normal">NotoSansSundanese-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Sylo">
         <font weight="400" style="normal">NotoSansSylotiNagri-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Syre">
         <font weight="400" style="normal">NotoSansSyriacEstrangela-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Tagb">
         <font weight="400" style="normal">NotoSansTagbanwa-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Lana">
         <font weight="400" style="normal">NotoSansTaiTham-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Tavt">
         <font weight="400" style="normal">NotoSansTaiViet-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Tibt">
         <font weight="400" style="normal">NotoSansTibetan-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Tfng">
         <font weight="400" style="normal">NotoSansTifinagh-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Vaii">
         <font weight="400" style="normal">NotoSansVai-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Yiii">
         <font weight="400" style="normal">NotoSansYi-Regular.ttf</font>
     </family>
     <family>
@@ -332,6 +336,7 @@
     <family lang="zh-Hans">
         <font weight="400" style="normal" index="2">NotoSansCJK-Regular.ttc</font>
     </family>
+    <!-- TODO: Add Bopo -->
     <family lang="zh-Hant">
         <font weight="400" style="normal" index="3">NotoSansCJK-Regular.ttc</font>
     </family>
@@ -351,10 +356,10 @@
         Tai Le and Mongolian are intentionally kept last, to make sure they don't override
         the East Asian punctuation for Chinese.
     -->
-    <family>
+    <family lang="und-Tale">
         <font weight="400" style="normal">NotoSansTaiLe-Regular.ttf</font>
     </family>
-    <family>
+    <family lang="und-Mong">
         <font weight="400" style="normal">NotoSansMongolian-Regular.ttf</font>
     </family>
 </familyset>
diff --git a/docs/docs-documentation-redirect.html b/docs/docs-documentation-redirect.html
index 98a265e..dbdf8b4 100644
--- a/docs/docs-documentation-redirect.html
+++ b/docs/docs-documentation-redirect.html
@@ -1,9 +1,9 @@
 <html>
 <head>
-<meta http-equiv="refresh" content="0;url=documentation.html">
+<meta http-equiv="refresh" content="0;url=reference/packages.html">
 </head>
 <body>
-<a href="documentation.html">click here if you are not redirected</a>
+<a href="reference/packages.html">click here if you are not redirected</a>
 </body>
 </html>
 
diff --git a/docs/docs-preview-index.html b/docs/docs-preview-index.html
new file mode 100644
index 0000000..e26b57c
--- /dev/null
+++ b/docs/docs-preview-index.html
@@ -0,0 +1,103 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
+<meta content="IE=edge" http-equiv="X-UA-Compatible">
+<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
+
+<title>Android N Developer Preview</title>
+
+<!-- STYLESHEETS -->
+<link rel="stylesheet"
+href="http://fonts.googleapis.com/css?family=Roboto+Condensed">
+<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold"
+  title="roboto">
+<link href="assets/css/default.css?v=17" rel="stylesheet" type="text/css">
+<!-- JAVASCRIPT -->
+<script src="https://www.google.com/jsapi" type="text/javascript"></script>
+<script src="assets/js/android_3p-bundle.js" type="text/javascript"></script>
+<script type="text/javascript">
+  var toRoot = "../";
+  var metaTags = ["develop, getstarted, sdk, appquality, landing"];
+  var devsite = false;
+</script>
+<script src="assets/js/docs.js?v=3" type="text/javascript"></script>
+</head>
+
+<body>
+<div id="header-wrapper">
+  <div class="dac-header" id="header">
+    <div class="dac-header-inner">
+      <a class="dac-nav-toggle" data-dac-toggle-nav="" href="javascript:;"
+        title="Open navigation">
+        <span class="dac-nav-hamburger">
+          <span class="dac-nav-hamburger-top"></span>
+          <span class="dac-nav-hamburger-mid"></span>
+          <span class="dac-nav-hamburger-bot"></span>
+        </span>
+      </a>
+      <a class="dac-header-logo" href="index.html">
+        <img class="dac-header-logo-image" src="assets/images/android_logo.png"
+          srcset="assets/images/android_logo@2x.png 2x" width="32" height="36"
+          alt="Android"> Developers
+        </a>
+    </div>
+  </div>
+</div>
+<nav class="dac-nav">
+  <div class="dac-nav-dimmer" data-dac-toggle-nav=""></div>
+  <ul class="dac-nav-list" data-dac-nav="">
+    <li class="dac-nav-item dac-nav-head">
+      <a class="dac-nav-link dac-nav-logo" data-dac-toggle-nav=""
+        href="javascript:;" title="Close navigation">
+        <img class="dac-logo-image" src="assets/images/android_logo.png"
+          srcset="assets/images/android_logo@2x.png 2x" width="32" height="36"
+          alt="Android"> Developers
+      </a>
+    </li>
+    <li class="dac-nav-item develop">
+      <a class="dac-nav-link" href="reference/packages.html"
+        >API Reference</a>
+    </li>
+  </ul>
+</nav>
+
+<section class="dac-expand" style="padding-top:40px;background-color:#eee">
+  <div class="wrap" style="max-width:1100px;margin-top:0;height:100%">
+    <div class="cols dac-hero-content" style="padding-bottom:1em;">
+      <div class="col-11of16">
+
+
+<h1>Android N Developer Preview</h1>
+<p>
+  Get ready for Android N!
+  <strong>Test your apps</strong> on Nexus devices. Support new system
+  behaviors to <strong>save power and memory</strong>.
+  Extend your apps with <strong>multi-window UI</strong>,
+  <strong>direct reply notifications</strong> and more.
+</p>
+
+<h2>Get Started</h2>
+<ul>
+  <li>View the <a href="reference/packages.html">API Reference</a></li>
+  <li>Read Diff Reports:</a>
+    <ul>
+      <li><a href="sdk/api_diff/n-preview-1/changes.html"
+        >API 23 --> Preview 1</a></li>
+    </ul>
+  </li>
+  <li>Downloads and additional documentation are available at the
+    <a href="http://developer.android.com/preview/index.html">
+      Android N Developer Preview site</a></li>
+  <li>For information about Developer Preview 1, visit the
+    <a href="http://developer.android.com/preview/support.html">Support</a>
+    page.</li>
+</ul>
+
+
+      </div>
+    </div>
+  </div>
+</section>
+</body>
+</html>
diff --git a/graphics/java/android/graphics/AvoidXfermode.java b/graphics/java/android/graphics/AvoidXfermode.java
index 48ee6fa..683c157 100644
--- a/graphics/java/android/graphics/AvoidXfermode.java
+++ b/graphics/java/android/graphics/AvoidXfermode.java
@@ -19,6 +19,8 @@
 /**
  * AvoidXfermode xfermode will draw the src everywhere except on top of the
  * opColor or, depending on the Mode, draw only on top of the opColor.
+ *
+ * @removed
  */
 @Deprecated
 public class AvoidXfermode extends Xfermode {
@@ -53,9 +55,5 @@
         if (tolerance < 0 || tolerance > 255) {
             throw new IllegalArgumentException("tolerance must be 0..255");
         }
-        native_instance = nativeCreate(opColor, tolerance, mode.nativeInt);
     }
-
-    private static native long nativeCreate(int opColor, int tolerance,
-                                            int nativeMode);
 }
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 99fa9fe..3e86e6f 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -32,13 +32,15 @@
  * @see Drawable#getOutline(Outline)
  */
 public final class Outline {
+    private static final float RADIUS_UNDEFINED = Float.NEGATIVE_INFINITY;
+
     /** @hide */
     public Path mPath;
 
     /** @hide */
     public Rect mRect;
     /** @hide */
-    public float mRadius;
+    public float mRadius = RADIUS_UNDEFINED;
     /** @hide */
     public float mAlpha;
 
@@ -63,7 +65,7 @@
     public void setEmpty() {
         mPath = null;
         mRect = null;
-        mRadius = 0;
+        mRadius = RADIUS_UNDEFINED;
     }
 
     /**
@@ -194,11 +196,11 @@
     }
 
     /**
-     * Returns the rounded rect radius, if set, or {@code -1} if a path has
+     * Returns the rounded rect radius, if set, or a value less than 0 if a path has
      * been set via {@link #setConvexPath(Path)}. A return value of {@code 0}
      * indicates a non-rounded rect.
      *
-     * @return the rounded rect radius or {@code -1}
+     * @return the rounded rect radius, or value < 0
      */
     public float getRadius() {
         return mRadius;
@@ -223,6 +225,7 @@
         mPath.reset();
         mPath.addOval(left, top, right, bottom, Path.Direction.CW);
         mRect = null;
+        mRadius = RADIUS_UNDEFINED;
     }
 
     /**
@@ -249,7 +252,7 @@
 
         mPath.set(convexPath);
         mRect = null;
-        mRadius = -1.0f;
+        mRadius = RADIUS_UNDEFINED;
     }
 
     /**
diff --git a/graphics/java/android/graphics/PixelXorXfermode.java b/graphics/java/android/graphics/PixelXorXfermode.java
index 0080e65..27884e0 100644
--- a/graphics/java/android/graphics/PixelXorXfermode.java
+++ b/graphics/java/android/graphics/PixelXorXfermode.java
@@ -17,17 +17,11 @@
 package android.graphics;
 
 /**
- * PixelXorXfermode implements a simple pixel xor (op ^ src ^ dst).
- * This transformation does not follow premultiplied conventions, therefore
- * this mode *always* returns an opaque color (alpha == 255). Thus it is
- * not really usefull for operating on blended colors.
+ * @removed
  */
 @Deprecated
 public class PixelXorXfermode extends Xfermode {
 
     public PixelXorXfermode(int opColor) {
-        native_instance = nativeCreate(opColor);
     }
-
-    private static native long nativeCreate(int opColor);
 }
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 0cde0b9..93ef3f0 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -30,6 +30,11 @@
  * These fields can be accessed directly. Use width() and height() to retrieve
  * the rectangle's width and height. Note: most methods do not check to see that
  * the coordinates are sorted correctly (i.e. left <= right and top <= bottom).
+ * <p>
+ * Note that the right and bottom coordinates are exclusive. This means a Rect
+ * being drawn untransformed onto a {@link android.graphics.Canvas} will draw
+ * into the column and row described by its left and top coordinates, but not
+ * those of its bottom and right.
  */
 public final class Rect implements Parcelable {
     public int left;
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 219bca8..ae9ebc7 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -27,6 +27,7 @@
 import android.annotation.Nullable;
 import android.app.ActivityThread;
 import android.app.Application;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -156,7 +157,7 @@
     private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
 
     /** Local, mutable animator set. */
-    private VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimatorRT(this);
+    private VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimatorUI(this);
 
     /**
      * The resources against which this drawable was created. Used to attempt
@@ -230,7 +231,7 @@
     }
 
     @Override
-    public int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         return super.getChangingConfigurations() | mAnimatedVectorState.getChangingConfigurations();
     }
 
@@ -260,6 +261,13 @@
         return mAnimatedVectorState.mVectorDrawable.setLayoutDirection(layoutDirection);
     }
 
+    /**
+     * AnimatedVectorDrawable is running on render thread now. Therefore, if the root alpha is being
+     * animated, then the root alpha value we get from this call could be out of sync with alpha
+     * value used in the render thread. Otherwise, the root alpha should be always the same value.
+     *
+     * @return the containing vector drawable's root alpha value.
+     */
     @Override
     public int getAlpha() {
         return mAnimatedVectorState.mVectorDrawable.getAlpha();
@@ -276,6 +284,11 @@
     }
 
     @Override
+    public ColorFilter getColorFilter() {
+        return mAnimatedVectorState.mVectorDrawable.getColorFilter();
+    }
+
+    @Override
     public void setTintList(ColorStateList tint) {
         mAnimatedVectorState.mVectorDrawable.setTintList(tint);
     }
@@ -437,7 +450,7 @@
     }
 
     private static class AnimatedVectorDrawableState extends ConstantState {
-        int mChangingConfigurations;
+        @Config int mChangingConfigurations;
         VectorDrawable mVectorDrawable;
 
         /** Animators that require a theme before inflation. */
@@ -501,7 +514,7 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mChangingConfigurations;
         }
 
@@ -703,17 +716,17 @@
 
     private final Callback mCallback = new Callback() {
         @Override
-        public void invalidateDrawable(Drawable who) {
+        public void invalidateDrawable(@NonNull Drawable who) {
             invalidateSelf();
         }
 
         @Override
-        public void scheduleDrawable(Drawable who, Runnable what, long when) {
+        public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
             scheduleSelf(what, when);
         }
 
         @Override
-        public void unscheduleDrawable(Drawable who, Runnable what) {
+        public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
             unscheduleSelf(what);
         }
     };
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index bffbc75..9d8ede0 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -17,6 +17,7 @@
 package android.graphics.drawable;
 
 import android.annotation.NonNull;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -454,7 +455,7 @@
     }
 
     @Override
-    public int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         return super.getChangingConfigurations() | mBitmapState.getChangingConfigurations();
     }
 
@@ -910,7 +911,7 @@
         int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
         boolean mAutoMirrored = false;
 
-        int mChangingConfigurations;
+        @Config int mChangingConfigurations;
         boolean mRebuildShader;
 
         BitmapState(Bitmap bitmap) {
@@ -958,7 +959,7 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mChangingConfigurations
                     | (mTint != null ? mTint.getChangingConfigurations() : 0);
         }
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index 5ad31f7..7524cac 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
+import android.content.pm.ActivityInfo.Config;
 import android.graphics.*;
 import android.graphics.PorterDuff.Mode;
 import android.content.res.ColorStateList;
@@ -70,7 +71,7 @@
     }
 
     @Override
-    public int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         return super.getChangingConfigurations() | mColorState.getChangingConfigurations();
     }
 
@@ -292,7 +293,7 @@
         int mBaseColor; // base color, independent of setAlpha()
         @ViewDebug.ExportedProperty
         int mUseColor;  // basecolor modulated by setAlpha()
-        int mChangingConfigurations;
+        @Config int mChangingConfigurations;
         ColorStateList mTint = null;
         Mode mTintMode = DEFAULT_TINT_MODE;
 
@@ -326,7 +327,7 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mChangingConfigurations
                     | (mTint != null ? mTint.getChangingConfigurations() : 0);
         }
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 3d8437d..3915984 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -19,6 +19,7 @@
 import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -134,7 +135,7 @@
 
     private int[] mStateSet = StateSet.WILD_CARD;
     private int mLevel = 0;
-    private int mChangingConfigurations = 0;
+    private @Config int mChangingConfigurations = 0;
     private Rect mBounds = ZERO_BOUNDS_RECT;  // lazily becomes a new Rect()
     private WeakReference<Callback> mCallback = null;
     private boolean mVisible = true;
@@ -249,7 +250,7 @@
      *
      * @see android.content.pm.ActivityInfo
      */
-    public void setChangingConfigurations(int configs) {
+    public void setChangingConfigurations(@Config int configs) {
         mChangingConfigurations = configs;
     }
 
@@ -266,7 +267,7 @@
      *
      * @see android.content.pm.ActivityInfo
      */
-    public int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         return mChangingConfigurations;
     }
 
@@ -308,7 +309,7 @@
      * to supply your implementation of the interface to the drawable; it uses
      * this interface to schedule and execute animation changes.
      */
-    public static interface Callback {
+    public interface Callback {
         /**
          * Called when the drawable needs to be redrawn.  A view at this point
          * should invalidate itself (or at least the part of itself where the
@@ -316,7 +317,7 @@
          *
          * @param who The drawable that is requesting the update.
          */
-        public void invalidateDrawable(Drawable who);
+        void invalidateDrawable(@NonNull Drawable who);
 
         /**
          * A Drawable can call this to schedule the next frame of its
@@ -330,7 +331,7 @@
          * @param when The time (in milliseconds) to run.  The timebase is
          *             {@link android.os.SystemClock#uptimeMillis}
          */
-        public void scheduleDrawable(Drawable who, Runnable what, long when);
+        void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when);
 
         /**
          * A Drawable can call this to unschedule an action previously
@@ -342,7 +343,7 @@
          * @param who The drawable being unscheduled.
          * @param what The action being unscheduled.
          */
-        public void unscheduleDrawable(Drawable who, Runnable what);
+        void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what);
     }
 
     /**
@@ -1294,7 +1295,7 @@
          * Return a bit mask of configuration changes that will impact
          * this drawable (and thus require completely reloading it).
          */
-        public abstract int getChangingConfigurations();
+        public abstract @Config int getChangingConfigurations();
 
         /**
          * @return Total pixel count
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 3b0e7e8..42f4863 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -17,6 +17,7 @@
 package android.graphics.drawable;
 
 import android.annotation.NonNull;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -87,7 +88,7 @@
     }
 
     @Override
-    public int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         return super.getChangingConfigurations()
                 | mDrawableContainerState.getChangingConfigurations();
     }
@@ -373,21 +374,21 @@
     }
 
     @Override
-    public void invalidateDrawable(Drawable who) {
+    public void invalidateDrawable(@NonNull Drawable who) {
         if (who == mCurrDrawable && getCallback() != null) {
             getCallback().invalidateDrawable(this);
         }
     }
 
     @Override
-    public void scheduleDrawable(Drawable who, Runnable what, long when) {
+    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
         if (who == mCurrDrawable && getCallback() != null) {
             getCallback().scheduleDrawable(this, what, when);
         }
     }
 
     @Override
-    public void unscheduleDrawable(Drawable who, Runnable what) {
+    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
         if (who == mCurrDrawable && getCallback() != null) {
             getCallback().unscheduleDrawable(this, what);
         }
@@ -649,8 +650,8 @@
 
         Resources mSourceRes;
         int mDensity = DisplayMetrics.DENSITY_DEFAULT;
-        int mChangingConfigurations;
-        int mChildrenChangingConfigurations;
+        @Config int mChangingConfigurations;
+        @Config int mChildrenChangingConfigurations;
 
         SparseArray<ConstantState> mDrawableFutures;
         Drawable[] mDrawables;
@@ -781,7 +782,7 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mChangingConfigurations | mChildrenChangingConfigurations;
         }
 
@@ -804,6 +805,7 @@
             mConstantPadding = null;
             mCheckedPadding = false;
             mCheckedConstantSize = false;
+            mCheckedConstantState = false;
 
             return pos;
         }
diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java
index c427870..5abfc54 100644
--- a/graphics/java/android/graphics/drawable/DrawableWrapper.java
+++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java
@@ -23,6 +23,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -198,7 +199,7 @@
     }
 
     @Override
-    public void invalidateDrawable(Drawable who) {
+    public void invalidateDrawable(@NonNull Drawable who) {
         final Callback callback = getCallback();
         if (callback != null) {
             callback.invalidateDrawable(this);
@@ -206,7 +207,7 @@
     }
 
     @Override
-    public void scheduleDrawable(Drawable who, Runnable what, long when) {
+    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
         final Callback callback = getCallback();
         if (callback != null) {
             callback.scheduleDrawable(this, what, when);
@@ -214,7 +215,7 @@
     }
 
     @Override
-    public void unscheduleDrawable(Drawable who, Runnable what) {
+    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
         final Callback callback = getCallback();
         if (callback != null) {
             callback.unscheduleDrawable(this, what);
@@ -229,7 +230,7 @@
     }
 
     @Override
-    public int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         return super.getChangingConfigurations()
                 | (mState != null ? mState.getChangingConfigurations() : 0)
                 | mDrawable.getChangingConfigurations();
@@ -444,7 +445,7 @@
     abstract static class DrawableWrapperState extends Drawable.ConstantState {
         private int[] mThemeAttrs;
 
-        int mChangingConfigurations;
+        @Config int mChangingConfigurations;
         int mDensity = DisplayMetrics.DENSITY_DEFAULT;
 
         Drawable.ConstantState mDrawableState;
@@ -524,7 +525,7 @@
         public abstract Drawable newDrawable(@Nullable Resources res);
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mChangingConfigurations
                     | (mDrawableState != null ? mDrawableState.getChangingConfigurations() : 0);
         }
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index f9208cd..bcc354c 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -17,8 +17,10 @@
 package android.graphics.drawable;
 
 import android.annotation.ColorInt;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -51,6 +53,8 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 /**
  * A Drawable with a color gradient for buttons, backgrounds, etc.
@@ -108,6 +112,11 @@
      */
     public static final int RING = 3;
 
+    /** @hide */
+    @IntDef({RECTANGLE, OVAL, LINE, RING})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Shape {}
+
     /**
      * Gradient is linear (default.)
      */
@@ -123,6 +132,11 @@
      */
     public static final int SWEEP_GRADIENT  = 2;
 
+    /** @hide */
+    @IntDef({LINEAR_GRADIENT, RADIAL_GRADIENT, SWEEP_GRADIENT})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface GradientType {}
+
     /** Radius is in pixels. */
     private static final int RADIUS_TYPE_PIXELS = 0;
 
@@ -132,6 +146,11 @@
     /** Radius is a fraction of the bounds size. */
     private static final int RADIUS_TYPE_FRACTION_PARENT = 2;
 
+    /** @hide */
+    @IntDef({RADIUS_TYPE_PIXELS, RADIUS_TYPE_FRACTION, RADIUS_TYPE_FRACTION_PARENT})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RadiusType {}
+
     private static final float DEFAULT_INNER_RADIUS_RATIO = 3.0f;
     private static final float DEFAULT_THICKNESS_RATIO = 9.0f;
 
@@ -404,7 +423,7 @@
      *
      * @see #mutate()
      */
-    public void setShape(int shape) {
+    public void setShape(@Shape int shape) {
         mRingPath = null;
         mPathIsDirty = true;
         mGradientState.setShape(shape);
@@ -412,6 +431,18 @@
     }
 
     /**
+     * Returns the type of shape used by this drawable, one of {@link #LINE},
+     * {@link #OVAL}, {@link #RECTANGLE} or {@link #RING}.
+     *
+     * @return the type of shape used by this drawable
+     * @see #setShape(int)
+     */
+    @Shape
+    public int getShape() {
+        return mGradientState.mShape;
+    }
+
+    /**
      * Sets the type of gradient used by this drawable.
      * <p>
      * <strong>Note</strong>: changing this property will affect all instances
@@ -424,7 +455,7 @@
      * @see #mutate()
      * @see #getGradientType()
      */
-    public void setGradientType(int gradient) {
+    public void setGradientType(@GradientType int gradient) {
         mGradientState.setGradientType(gradient);
         mGradientIsDirty = true;
         invalidateSelf();
@@ -438,6 +469,7 @@
      * @return the type of gradient used by this drawable
      * @see #setGradientType(int)
      */
+    @GradientType
     public int getGradientType() {
         return mGradientState.mGradient;
     }
@@ -534,7 +566,7 @@
      * @see #mutate()
      * @see #setLevel(int)
      * @see #getLevel()
-     * @see #isUseLevel()
+     * @see #getUseLevel()
      */
     public void setUseLevel(boolean useLevel) {
         mGradientState.mUseLevel = useLevel;
@@ -550,7 +582,7 @@
      *         {@code false} otherwise
      * @see #setUseLevel(boolean)
      */
-    public boolean isUseLevel() {
+    public boolean getUseLevel() {
         return mGradientState.mUseLevel;
     }
 
@@ -616,7 +648,8 @@
      */
     @Nullable
     public int[] getColors() {
-        return mGradientState.mGradientColors.clone();
+        return mGradientState.mGradientColors == null ?
+                null : mGradientState.mGradientColors.clone();
     }
 
     @Override
@@ -848,7 +881,7 @@
      * @see #mutate()
      * @see #getColor
      */
-    public void setColor(ColorStateList colorStateList) {
+    public void setColor(@Nullable ColorStateList colorStateList) {
         mGradientState.setSolidColors(colorStateList);
         final int color;
         if (colorStateList == null) {
@@ -870,6 +903,7 @@
      * @see #setColor(int)
      * @see #setColor(ColorStateList)
      */
+    @Nullable
     public ColorStateList getColor() {
         return mGradientState.mSolidColors;
     }
@@ -925,7 +959,7 @@
     }
 
     @Override
-    public int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         return super.getChangingConfigurations() | mGradientState.getChangingConfigurations();
     }
 
@@ -951,12 +985,13 @@
     }
 
     @Override
+    @Nullable
     public ColorFilter getColorFilter() {
         return mColorFilter;
     }
 
     @Override
-    public void setColorFilter(ColorFilter colorFilter) {
+    public void setColorFilter(@Nullable ColorFilter colorFilter) {
         if (colorFilter != mColorFilter) {
             mColorFilter = colorFilter;
             invalidateSelf();
@@ -964,14 +999,14 @@
     }
 
     @Override
-    public void setTintList(ColorStateList tint) {
+    public void setTintList(@Nullable ColorStateList tint) {
         mGradientState.mTint = tint;
         mTintFilter = updateTintFilter(mTintFilter, tint, mGradientState.mTintMode);
         invalidateSelf();
     }
 
     @Override
-    public void setTintMode(PorterDuff.Mode tintMode) {
+    public void setTintMode(@Nullable PorterDuff.Mode tintMode) {
         mGradientState.mTintMode = tintMode;
         mTintFilter = updateTintFilter(mTintFilter, mGradientState.mTint, tintMode);
         invalidateSelf();
@@ -1543,7 +1578,7 @@
             final TypedValue tv = a.peekValue(R.styleable.GradientDrawableGradient_gradientRadius);
             if (tv != null) {
                 final float radius;
-                final int radiusType;
+                final @RadiusType int radiusType;
                 if (tv.type == TypedValue.TYPE_FRACTION) {
                     radius = tv.getFraction(1.0f, 1.0f);
 
@@ -1624,7 +1659,9 @@
             return false;
         }
 
-        if (!isOpaque(mFillPaint.getColor())) {
+        // Don't check opacity if we're using a gradient, as we've already
+        // checked the gradient opacity in mOpaqueOverShape.
+        if (mGradientState.mGradientColors == null && !isOpaque(mFillPaint.getColor())) {
             return false;
         }
 
@@ -1698,15 +1735,15 @@
     }
 
     final static class GradientState extends ConstantState {
-        public int mChangingConfigurations;
-        public int mShape = RECTANGLE;
-        public int mGradient = LINEAR_GRADIENT;
+        public @Config int mChangingConfigurations;
+        public @Shape int mShape = RECTANGLE;
+        public @GradientType int mGradient = LINEAR_GRADIENT;
         public int mAngle = 0;
         public Orientation mOrientation;
         public ColorStateList mSolidColors;
         public ColorStateList mStrokeColors;
-        public int[] mGradientColors;
-        public int[] mTempColors; // no need to copy
+        public @ColorInt int[] mGradientColors;
+        public @ColorInt int[] mTempColors; // no need to copy
         public float[] mTempPositions; // no need to copy
         public float[] mPositions;
         public int mStrokeWidth = -1; // if >= 0 use stroking.
@@ -1727,7 +1764,7 @@
         float mCenterX = 0.5f;
         float mCenterY = 0.5f;
         float mGradientRadius = 0.5f;
-        int mGradientRadiusType = RADIUS_TYPE_PIXELS;
+        @RadiusType int mGradientRadiusType = RADIUS_TYPE_PIXELS;
         boolean mUseLevel = false;
         boolean mUseLevelForShape = true;
 
@@ -1926,19 +1963,19 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mChangingConfigurations
                     | (mStrokeColors != null ? mStrokeColors.getChangingConfigurations() : 0)
                     | (mSolidColors != null ? mSolidColors.getChangingConfigurations() : 0)
                     | (mTint != null ? mTint.getChangingConfigurations() : 0);
         }
 
-        public void setShape(int shape) {
+        public void setShape(@Shape int shape) {
             mShape = shape;
             computeOpacity();
         }
 
-        public void setGradientType(int gradient) {
+        public void setGradientType(@GradientType int gradient) {
             mGradient = gradient;
         }
 
@@ -1947,13 +1984,13 @@
             mCenterY = y;
         }
 
-        public void setGradientColors(int[] colors) {
+        public void setGradientColors(@Nullable int[] colors) {
             mGradientColors = colors;
             mSolidColors = null;
             computeOpacity();
         }
 
-        public void setSolidColors(ColorStateList colors) {
+        public void setSolidColors(@Nullable ColorStateList colors) {
             mGradientColors = null;
             mSolidColors = colors;
             computeOpacity();
@@ -1984,7 +2021,8 @@
                     && mRadiusArray == null;
         }
 
-        public void setStroke(int width, ColorStateList colors, float dashWidth, float dashGap) {
+        public void setStroke(int width, @Nullable ColorStateList colors, float dashWidth,
+                float dashGap) {
             mStrokeWidth = width;
             mStrokeColors = colors;
             mStrokeDashWidth = dashWidth;
@@ -2012,7 +2050,7 @@
             mHeight = height;
         }
 
-        public void setGradientRadius(float gradientRadius, int type) {
+        public void setGradientRadius(float gradientRadius, @RadiusType int type) {
             mGradientRadius = gradientRadius;
             mGradientRadiusType = type;
         }
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 0de4c2c..51221b4 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -627,6 +627,11 @@
         return this;
     }
 
+    /** @hide */
+    public boolean hasTint() {
+        return (mTintList != null) || (mTintMode != DEFAULT_TINT_MODE);
+    }
+
     /**
      * Create an Icon pointing to an image file specified by path.
      *
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index e2150c0..d9c3a02 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -88,7 +89,7 @@
      * @see #getLayerInsetStart(int)
      * @see #getLayerInsetEnd(int)
      */
-    public static final int UNDEFINED_INSET = Integer.MIN_VALUE;
+    public static final int INSET_UNDEFINED = Integer.MIN_VALUE;
 
     LayerState mLayerState;
 
@@ -758,7 +759,7 @@
      * @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);
+        setLayerInsetInternal(index, l, t, r, b, INSET_UNDEFINED, INSET_UNDEFINED);
     }
 
     /**
@@ -873,7 +874,7 @@
     /**
      * @param index the index of the layer
      * @return the number of pixels to inset from the start bound, or
-     *         {@link #UNDEFINED_INSET} if not specified
+     *         {@link #INSET_UNDEFINED} if not specified
      * @attr ref android.R.styleable#LayerDrawableItem_start
      */
     public int getLayerInsetStart(int index) {
@@ -884,7 +885,7 @@
     /**
      * @param index the index of the layer to adjust
      * @param e number of pixels to inset from the end bound, or
-     *         {@link #UNDEFINED_INSET} if not specified
+     *         {@link #INSET_UNDEFINED} if not specified
      * @attr ref android.R.styleable#LayerDrawableItem_end
      */
     public void setLayerInsetEnd(int index, int e) {
@@ -944,17 +945,17 @@
     }
 
     @Override
-    public void invalidateDrawable(Drawable who) {
+    public void invalidateDrawable(@NonNull Drawable who) {
         invalidateSelf();
     }
 
     @Override
-    public void scheduleDrawable(Drawable who, Runnable what, long when) {
+    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
         scheduleSelf(what, when);
     }
 
     @Override
-    public void unscheduleDrawable(Drawable who, Runnable what) {
+    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
         unscheduleSelf(what);
     }
 
@@ -971,7 +972,7 @@
     }
 
     @Override
-    public int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         return super.getChangingConfigurations() | mLayerState.getChangingConfigurations();
     }
 
@@ -1502,8 +1503,8 @@
             // insets.
             final int insetRtlL = isLayoutRtl ? r.mInsetE : r.mInsetS;
             final int insetRtlR = isLayoutRtl ? r.mInsetS : r.mInsetE;
-            final int insetL = insetRtlL == UNDEFINED_INSET ? r.mInsetL : insetRtlL;
-            final int insetR = insetRtlR == UNDEFINED_INSET ? r.mInsetR : insetRtlR;
+            final int insetL = insetRtlL == INSET_UNDEFINED ? r.mInsetL : insetRtlL;
+            final int insetR = insetRtlR == INSET_UNDEFINED ? r.mInsetR : insetRtlR;
 
             // Establish containing region based on aggregate padding and
             // requested insets for the current layer.
@@ -1601,8 +1602,8 @@
             // left / right ones.
             final int insetRtlL = isLayoutRtl ? r.mInsetE : r.mInsetS;
             final int insetRtlR = isLayoutRtl ? r.mInsetS : r.mInsetE;
-            final int insetL = insetRtlL == UNDEFINED_INSET ? r.mInsetL : insetRtlL;
-            final int insetR = insetRtlR == UNDEFINED_INSET ? r.mInsetR : insetRtlR;
+            final int insetL = insetRtlL == INSET_UNDEFINED ? r.mInsetL : insetRtlL;
+            final int insetR = insetRtlR == INSET_UNDEFINED ? r.mInsetR : insetRtlR;
 
             // Don't apply padding and insets for children that don't have
             // an intrinsic dimension.
@@ -1762,8 +1763,8 @@
         public int[] mThemeAttrs;
         public int mDensity = DisplayMetrics.DENSITY_DEFAULT;
         public int mInsetL, mInsetT, mInsetR, mInsetB;
-        public int mInsetS = UNDEFINED_INSET;
-        public int mInsetE = UNDEFINED_INSET;
+        public int mInsetS = INSET_UNDEFINED;
+        public int mInsetE = INSET_UNDEFINED;
         public int mWidth = -1;
         public int mHeight = -1;
         public int mGravity = Gravity.NO_GRAVITY;
@@ -1832,10 +1833,10 @@
             mInsetT = Drawable.scaleFromDensity(mInsetT, sourceDensity, targetDensity, false);
             mInsetR = Drawable.scaleFromDensity(mInsetR, sourceDensity, targetDensity, false);
             mInsetB = Drawable.scaleFromDensity(mInsetB, sourceDensity, targetDensity, false);
-            if (mInsetS != UNDEFINED_INSET) {
+            if (mInsetS != INSET_UNDEFINED) {
                 mInsetS = Drawable.scaleFromDensity(mInsetS, sourceDensity, targetDensity, false);
             }
-            if (mInsetE != UNDEFINED_INSET) {
+            if (mInsetE != INSET_UNDEFINED) {
                 mInsetE = Drawable.scaleFromDensity(mInsetE, sourceDensity, targetDensity, false);
             }
             if (mWidth > 0) {
@@ -1864,8 +1865,8 @@
         int mPaddingEnd = -1;
         int mOpacityOverride = PixelFormat.UNKNOWN;
 
-        int mChangingConfigurations;
-        int mChildrenChangingConfigurations;
+        @Config int mChangingConfigurations;
+        @Config int mChildrenChangingConfigurations;
 
         private boolean mHaveOpacity;
         private int mOpacity;
@@ -1989,7 +1990,7 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mChangingConfigurations
                     | mChildrenChangingConfigurations;
         }
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 6816539..fd3b9b4 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -260,7 +261,7 @@
     }
 
     @Override
-    public int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         return super.getChangingConfigurations() | mNinePatchState.getChangingConfigurations();
     }
 
@@ -575,7 +576,7 @@
     }
 
     final static class NinePatchState extends ConstantState {
-        int mChangingConfigurations;
+        @Config int mChangingConfigurations;
 
         // Values loaded during inflation.
         NinePatch mNinePatch = null;
@@ -651,7 +652,7 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mChangingConfigurations
                     | (mTint != null ? mTint.getChangingConfigurations() : 0);
         }
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index ee0861a..caf2e7a 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -23,6 +23,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -1033,7 +1034,7 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return super.getChangingConfigurations()
                     | (mColor != null ? mColor.getChangingConfigurations() : 0);
         }
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 30b588e..fe82a93 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -16,6 +16,7 @@
 
 package android.graphics.drawable;
 
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -260,7 +261,7 @@
     }
 
     @Override
-    public int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         return super.getChangingConfigurations() | mShapeState.getChangingConfigurations();
     }
 
@@ -526,7 +527,7 @@
      */
     final static class ShapeState extends ConstantState {
         int[] mThemeAttrs;
-        int mChangingConfigurations;
+        @Config int mChangingConfigurations;
         Paint mPaint;
         Shape mShape;
         ColorStateList mTint = null;
@@ -571,7 +572,7 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mChangingConfigurations
                     | (mTint != null ? mTint.getChangingConfigurations() : 0);
         }
diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java
index e5c235e..0122338 100644
--- a/graphics/java/android/graphics/drawable/TransitionDrawable.java
+++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java
@@ -16,6 +16,7 @@
 
 package android.graphics.drawable;
 
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.os.SystemClock;
@@ -259,7 +260,7 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mChangingConfigurations;
         }
     }
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 44a91fe..bd069ff 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -16,6 +16,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.ComplexColor;
 import android.content.res.GradientColor;
@@ -686,7 +687,7 @@
     }
 
     @Override
-    public int getChangingConfigurations() {
+    public @Config int getChangingConfigurations() {
         return super.getChangingConfigurations() | mVectorState.getChangingConfigurations();
     }
 
@@ -714,7 +715,7 @@
     static class VectorDrawableState extends ConstantState {
         // Variables below need to be copied (deep copy if applicable) for mutation.
         int[] mThemeAttrs;
-        int mChangingConfigurations;
+        @Config int mChangingConfigurations;
         ColorStateList mTint = null;
         Mode mTintMode = DEFAULT_TINT_MODE;
         boolean mAutoMirrored;
@@ -823,7 +824,7 @@
         }
 
         @Override
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mChangingConfigurations
                     | (mTint != null ? mTint.getChangingConfigurations() : 0);
         }
@@ -923,7 +924,7 @@
 
         // mLocalMatrix is updated based on the update of transformation information,
         // either parsed from the XML or by animation.
-        private int mChangingConfigurations;
+        private @Config int mChangingConfigurations;
         private int[] mThemeAttrs;
         private String mGroupName = null;
 
@@ -1169,7 +1170,7 @@
         protected PathParser.PathData mPathData = null;
 
         String mPathName;
-        int mChangingConfigurations;
+        @Config int mChangingConfigurations;
 
         public VPath() {
             // Empty constructor.
@@ -1280,8 +1281,10 @@
         private static final int STROKE_LINE_CAP_INDEX = 8;
         private static final int STROKE_LINE_JOIN_INDEX = 9;
         private static final int STROKE_MITER_LIMIT_INDEX = 10;
-        private static final int TOTAL_PROPERTY_COUNT = 11;
+        private static final int FILL_TYPE_INDEX = 11;
+        private static final int TOTAL_PROPERTY_COUNT = 12;
 
+        // Property map for animatable attributes.
         private final static HashMap<String, Integer> sPropertyMap
                 = new HashMap<String, Integer> () {
             {
@@ -1398,6 +1401,7 @@
             int strokeLineCap =  properties.getInt(STROKE_LINE_CAP_INDEX * 4);
             int strokeLineJoin = properties.getInt(STROKE_LINE_JOIN_INDEX * 4);
             float strokeMiterLimit = properties.getFloat(STROKE_MITER_LIMIT_INDEX * 4);
+            int fillType = properties.getInt(FILL_TYPE_INDEX * 4);
             Shader fillGradient = null;
             Shader strokeGradient = null;
             // Account for any configuration changes.
@@ -1473,10 +1477,11 @@
                     R.styleable.VectorDrawablePath_trimPathOffset, trimPathOffset);
             trimPathStart = a.getFloat(
                     R.styleable.VectorDrawablePath_trimPathStart, trimPathStart);
+            fillType = a.getInt(R.styleable.VectorDrawablePath_fillType, fillType);
 
             nUpdateFullPathProperties(mNativePtr, strokeWidth, strokeColor, strokeAlpha,
                     fillColor, fillAlpha, trimPathStart, trimPathEnd, trimPathOffset,
-                    strokeMiterLimit, strokeLineCap, strokeLineJoin);
+                    strokeMiterLimit, strokeLineCap, strokeLineJoin, fillType);
         }
 
         @Override
@@ -1644,7 +1649,7 @@
     private static native void nUpdateFullPathProperties(long pathPtr, float strokeWidth,
             int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
             float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
-            int strokeLineJoin);
+            int strokeLineJoin, int fillType);
     private static native void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr);
     private static native void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr);
 
diff --git a/graphics/java/android/graphics/drawable/shapes/ArcShape.java b/graphics/java/android/graphics/drawable/shapes/ArcShape.java
index 84731b0..c4b239f 100644
--- a/graphics/java/android/graphics/drawable/shapes/ArcShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/ArcShape.java
@@ -17,6 +17,7 @@
 package android.graphics.drawable.shapes;
 
 import android.graphics.Canvas;
+import android.graphics.Outline;
 import android.graphics.Paint;
 
 /**
@@ -46,5 +47,11 @@
     public void draw(Canvas canvas, Paint paint) {
         canvas.drawArc(rect(), mStart, mSweep, true, paint);
     }
+
+    @Override
+    public void getOutline(Outline outline) {
+        // Since we don't support concave outlines, arc shape does not attempt
+        // to provide an outline.
+    }
 }
 
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 6813c89..05596f0 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -35,6 +35,8 @@
 
 #include <android/configuration.h>
 
+#include <memory>
+
 namespace android {
 
 /**
@@ -1876,9 +1878,30 @@
     struct Entry;
     struct Package;
     struct PackageGroup;
-    struct bag_set;
     typedef Vector<Type*> TypeList;
 
+    struct bag_set {
+        size_t numAttrs;    // number in array
+        size_t availAttrs;  // total space in array
+        uint32_t typeSpecFlags;
+        // Followed by 'numAttr' bag_entry structures.
+    };
+
+    /**
+     * Configuration dependent cached data. This must be cleared when the configuration is
+     * changed (setParameters).
+     */
+    struct TypeCacheEntry {
+        TypeCacheEntry() : cachedBags(NULL) {}
+
+        // Computed attribute bags for this type.
+        bag_set** cachedBags;
+
+        // Pre-filtered list of configurations (per asset path) that match the parameters set on this
+        // ResTable.
+        Vector<std::shared_ptr<Vector<const ResTable_type*>>> filteredConfigs;
+    };
+
     status_t addInternal(const void* data, size_t size, const void* idmapData, size_t idmapDataSize,
             bool appAsLib, const int32_t cookie, bool copyData, bool isSystemAsset=false);
 
@@ -1900,6 +1923,13 @@
 
     mutable Mutex               mLock;
 
+    // Mutex that controls access to the list of pre-filtered configurations
+    // to check when looking up entries.
+    // When iterating over a bag, the mLock mutex is locked. While mLock is locked,
+    // we do resource lookups.
+    // Mutex is not reentrant, so we must use a different lock than mLock.
+    mutable Mutex               mFilteredConfigLock;
+
     status_t                    mError;
 
     ResTable_config             mParams;
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index bf6ff11..52fe973 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -25,6 +25,7 @@
 #include <string.h>
 
 #include <limits>
+#include <memory>
 #include <type_traits>
 
 #include <androidfw/ByteBucketArray.h>
@@ -3193,7 +3194,6 @@
         , name(_name)
         , id(_id)
         , largestTypeId(0)
-        , bags(NULL)
         , dynamicRefTable(static_cast<uint8_t>(_id), appAsLib)
         , isSystemAsset(_isSystemAsset)
     { }
@@ -3220,36 +3220,41 @@
         }
     }
 
+    /**
+     * Clear all cache related data that depends on parameters/configuration.
+     * This includes the bag caches and filtered types.
+     */
     void clearBagCache() {
-        if (bags) {
+        for (size_t i = 0; i < typeCacheEntries.size(); i++) {
             if (kDebugTableNoisy) {
-                printf("bags=%p\n", bags);
+                printf("type=%zu\n", i);
             }
-            for (size_t i = 0; i < bags->size(); i++) {
+            const TypeList& typeList = types[i];
+            if (!typeList.isEmpty()) {
+                TypeCacheEntry& cacheEntry = typeCacheEntries.editItemAt(i);
+
+                // Reset the filtered configurations.
+                cacheEntry.filteredConfigs.clear();
+
+                bag_set** typeBags = cacheEntry.cachedBags;
                 if (kDebugTableNoisy) {
-                    printf("type=%zu\n", i);
+                    printf("typeBags=%p\n", typeBags);
                 }
-                const TypeList& typeList = types[i];
-                if (!typeList.isEmpty()) {
-                    bag_set** typeBags = bags->get(i);
+
+                if (typeBags) {
+                    const size_t N = typeList[0]->entryCount;
                     if (kDebugTableNoisy) {
-                        printf("typeBags=%p\n", typeBags);
+                        printf("type->entryCount=%zu\n", N);
                     }
-                    if (typeBags) {
-                        const size_t N = typeList[0]->entryCount;
-                        if (kDebugTableNoisy) {
-                            printf("type->entryCount=%zu\n", N);
+                    for (size_t j = 0; j < N; j++) {
+                        if (typeBags[j] && typeBags[j] != (bag_set*)0xFFFFFFFF) {
+                            free(typeBags[j]);
                         }
-                        for (size_t j = 0; j < N; j++) {
-                            if (typeBags[j] && typeBags[j] != (bag_set*)0xFFFFFFFF)
-                                free(typeBags[j]);
-                        }
-                        free(typeBags);
                     }
+                    free(typeBags);
+                    cacheEntry.cachedBags = NULL;
                 }
             }
-            delete bags;
-            bags = NULL;
         }
     }
 
@@ -3277,9 +3282,11 @@
 
     uint8_t                         largestTypeId;
 
-    // Computed attribute bags, first indexed by the type and second
-    // by the entry in that type.
-    ByteBucketArray<bag_set**>*     bags;
+    // Cached objects dependent on the parameters/configuration of this ResTable.
+    // Gets cleared whenever the parameters/configuration changes.
+    // These are stored here in a parallel structure because the data in `types` may
+    // be shared by other ResTable's (framework resources are shared this way).
+    ByteBucketArray<TypeCacheEntry> typeCacheEntries;
 
     // The table mapping dynamic references to resolved references for
     // this package group.
@@ -3293,14 +3300,6 @@
     const bool                      isSystemAsset;
 };
 
-struct ResTable::bag_set
-{
-    size_t numAttrs;    // number in array
-    size_t availAttrs;  // total space in array
-    uint32_t typeSpecFlags;
-    // Followed by 'numAttr' bag_entry structures.
-};
-
 ResTable::Theme::Theme(const ResTable& table)
     : mTable(table)
     , mTypeSpecFlags(0)
@@ -4192,39 +4191,32 @@
     }
 
     // First see if we've already computed this bag...
-    if (grp->bags) {
-        bag_set** typeSet = grp->bags->get(t);
-        if (typeSet) {
-            bag_set* set = typeSet[e];
-            if (set) {
-                if (set != (bag_set*)0xFFFFFFFF) {
-                    if (outTypeSpecFlags != NULL) {
-                        *outTypeSpecFlags = set->typeSpecFlags;
-                    }
-                    *outBag = (bag_entry*)(set+1);
-                    if (kDebugTableSuperNoisy) {
-                        ALOGI("Found existing bag for: 0x%x\n", resID);
-                    }
-                    return set->numAttrs;
+    TypeCacheEntry& cacheEntry = grp->typeCacheEntries.editItemAt(t);
+    bag_set** typeSet = cacheEntry.cachedBags;
+    if (typeSet) {
+        bag_set* set = typeSet[e];
+        if (set) {
+            if (set != (bag_set*)0xFFFFFFFF) {
+                if (outTypeSpecFlags != NULL) {
+                    *outTypeSpecFlags = set->typeSpecFlags;
                 }
-                ALOGW("Attempt to retrieve bag 0x%08x which is invalid or in a cycle.",
-                     resID);
-                return BAD_INDEX;
+                *outBag = (bag_entry*)(set+1);
+                if (kDebugTableSuperNoisy) {
+                    ALOGI("Found existing bag for: 0x%x\n", resID);
+                }
+                return set->numAttrs;
             }
+            ALOGW("Attempt to retrieve bag 0x%08x which is invalid or in a cycle.",
+                 resID);
+            return BAD_INDEX;
         }
     }
 
     // Bag not found, we need to compute it!
-    if (!grp->bags) {
-        grp->bags = new ByteBucketArray<bag_set**>();
-        if (!grp->bags) return NO_MEMORY;
-    }
-
-    bag_set** typeSet = grp->bags->get(t);
     if (!typeSet) {
         typeSet = (bag_set**)calloc(NENTRY, sizeof(bag_set*));
         if (!typeSet) return NO_MEMORY;
-        grp->bags->set(t, typeSet);
+        cacheEntry.cachedBags = typeSet;
     }
 
     // Mark that we are currently working on this one.
@@ -4430,18 +4422,56 @@
 
 void ResTable::setParameters(const ResTable_config* params)
 {
-    mLock.lock();
+    AutoMutex _lock(mLock);
+    AutoMutex _lock2(mFilteredConfigLock);
+
     if (kDebugTableGetEntry) {
         ALOGI("Setting parameters: %s\n", params->toString().string());
     }
     mParams = *params;
-    for (size_t i=0; i<mPackageGroups.size(); i++) {
+    for (size_t p = 0; p < mPackageGroups.size(); p++) {
+        PackageGroup* packageGroup = mPackageGroups.editItemAt(p);
         if (kDebugTableNoisy) {
-            ALOGI("CLEARING BAGS FOR GROUP %zu!", i);
+            ALOGI("CLEARING BAGS FOR GROUP %zu!", p);
         }
-        mPackageGroups[i]->clearBagCache();
+        packageGroup->clearBagCache();
+
+        // Find which configurations match the set of parameters. This allows for a much
+        // faster lookup in getEntry() if the set of values is narrowed down.
+        for (size_t t = 0; t < packageGroup->types.size(); t++) {
+            if (packageGroup->types[t].isEmpty()) {
+                continue;
+            }
+
+            TypeList& typeList = packageGroup->types.editItemAt(t);
+
+            // Retrieve the cache entry for this type.
+            TypeCacheEntry& cacheEntry = packageGroup->typeCacheEntries.editItemAt(t);
+
+            for (size_t ts = 0; ts < typeList.size(); ts++) {
+                Type* type = typeList.editItemAt(ts);
+
+                std::shared_ptr<Vector<const ResTable_type*>> newFilteredConfigs =
+                        std::make_shared<Vector<const ResTable_type*>>();
+
+                for (size_t ti = 0; ti < type->configs.size(); ti++) {
+                    ResTable_config config;
+                    config.copyFromDtoH(type->configs[ti]->config);
+
+                    if (config.match(mParams)) {
+                        newFilteredConfigs->add(type->configs[ti]);
+                    }
+                }
+
+                if (kDebugTableNoisy) {
+                    ALOGD("Updating pkg=%zu type=%zu with %zu filtered configs",
+                          p, t, newFilteredConfigs->size());
+                }
+
+                cacheEntry.filteredConfigs.add(newFilteredConfigs);
+            }
+        }
     }
-    mLock.unlock();
 }
 
 void ResTable::getParameters(ResTable_config* params) const
@@ -5974,9 +6004,32 @@
             specFlags = -1;
         }
 
-        const size_t numConfigs = typeSpec->configs.size();
+        const Vector<const ResTable_type*>* candidateConfigs = &typeSpec->configs;
+
+        std::shared_ptr<Vector<const ResTable_type*>> filteredConfigs;
+        if (config && memcmp(&mParams, config, sizeof(mParams)) == 0) {
+            // Grab the lock first so we can safely get the current filtered list.
+            AutoMutex _lock(mFilteredConfigLock);
+
+            // This configuration is equal to the one we have previously cached for,
+            // so use the filtered configs.
+
+            const TypeCacheEntry& cacheEntry = packageGroup->typeCacheEntries[typeIndex];
+            if (i < cacheEntry.filteredConfigs.size()) {
+                if (cacheEntry.filteredConfigs[i]) {
+                    // Grab a reference to the shared_ptr so it doesn't get destroyed while
+                    // going through this list.
+                    filteredConfigs = cacheEntry.filteredConfigs[i];
+
+                    // Use this filtered list.
+                    candidateConfigs = filteredConfigs.get();
+                }
+            }
+        }
+
+        const size_t numConfigs = candidateConfigs->size();
         for (size_t c = 0; c < numConfigs; c++) {
-            const ResTable_type* const thisType = typeSpec->configs[c];
+            const ResTable_type* const thisType = candidateConfigs->itemAt(c);
             if (thisType == NULL) {
                 continue;
             }
diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp
index dcfe91e..7cd7fb5 100644
--- a/libs/androidfw/tests/ResTable_test.cpp
+++ b/libs/androidfw/tests/ResTable_test.cpp
@@ -282,4 +282,46 @@
     testU16StringToInt(u"0x1ffffffff", 0U, false, true);
 }
 
+TEST(ResTableTest, ShareButDontModifyResTable) {
+    ResTable sharedTable;
+    ASSERT_EQ(NO_ERROR, sharedTable.add(basic_arsc, basic_arsc_len));
+
+    ResTable_config param;
+    memset(&param, 0, sizeof(param));
+    param.language[0] = 'v';
+    param.language[1] = 's';
+    sharedTable.setParameters(&param);
+
+    // Check that we get the default value for @integer:number1
+    Res_value val;
+    ssize_t block = sharedTable.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
+    ASSERT_GE(block, 0);
+    ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+    ASSERT_EQ(uint32_t(600), val.data);
+
+    // Create a new table that shares the entries of the shared table.
+    ResTable table;
+    ASSERT_EQ(NO_ERROR, table.add(&sharedTable, false));
+
+    // Set a new configuration on the new table.
+    memset(&param, 0, sizeof(param));
+    param.language[0] = 's';
+    param.language[1] = 'v';
+    param.country[0] = 'S';
+    param.country[1] = 'E';
+    table.setParameters(&param);
+
+    // Check that we get a new value in the new table.
+    block = table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
+    ASSERT_GE(block, 0);
+    ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+    ASSERT_EQ(uint32_t(400), val.data);
+
+    // Check that we still get the old value in the shared table.
+    block = sharedTable.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG);
+    ASSERT_GE(block, 0);
+    ASSERT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
+    ASSERT_EQ(uint32_t(600), val.data);
 }
+
+} // namespace
diff --git a/libs/androidfw/tests/data/basic/R.h b/libs/androidfw/tests/data/basic/R.h
index aaac740..6694dd0 100644
--- a/libs/androidfw/tests/data/basic/R.h
+++ b/libs/androidfw/tests/data/basic/R.h
@@ -46,7 +46,7 @@
 
 namespace integer {
     enum {
-        number1     = 0x7f040000,   // default, sv
+        number1     = 0x7f040000,   // default, sv, vs
         number2     = 0x7f040001,   // default
 
         test3       = 0x7f090000,   // default (in feature)
diff --git a/libs/androidfw/tests/data/basic/basic_arsc.h b/libs/androidfw/tests/data/basic/basic_arsc.h
index 13ab4fa..e497401 100644
--- a/libs/androidfw/tests/data/basic/basic_arsc.h
+++ b/libs/androidfw/tests/data/basic/basic_arsc.h
@@ -1,5 +1,5 @@
 unsigned char basic_arsc[] = {
-  0x02, 0x00, 0x0c, 0x00, 0x68, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x0c, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x1c, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
@@ -16,7 +16,7 @@
   0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
   0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
   0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01,
-  0xa0, 0x06, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
+  0x44, 0x07, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
   0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
   0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00,
   0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00,
@@ -73,68 +73,81 @@
   0x41, 0x00, 0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x31, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x84, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x8c, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+  0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x08, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00,
-  0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10,
-  0x05, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x24, 0x00, 0x00,
-  0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x04, 0x24, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
+  0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x72, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
+  0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x66, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02,
+  0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
   0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
   0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x02, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x01, 0x02, 0x4c, 0x00, 0x78, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
-  0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x02, 0x4c, 0x00, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0xc8, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01,
-  0x00, 0x00, 0x06, 0x7f, 0x01, 0x02, 0x44, 0x00, 0x5c, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x76, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
+  0xc8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x7f, 0x01, 0x02, 0x4c, 0x00,
+  0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x54, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x76, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x90, 0x01, 0x00, 0x00,
-  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x02, 0x44, 0x00, 0x90, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x58, 0x02, 0x00, 0x00,
+  0x01, 0x02, 0x4c, 0x00, 0x64, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x73, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
+  0x90, 0x01, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x98, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+  0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -146,16 +159,17 @@
   0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x7f, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, 0x2c, 0x01, 0x00, 0x00,
   0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
-  0x7c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-  0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
+  0x84, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x50, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
-  0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x00
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02,
+  0x08, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02,
+  0x08, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x00
 };
-unsigned int basic_arsc_len = 1896;
+unsigned int basic_arsc_len = 2060;
diff --git a/packages/DocumentsUI/res/animator/dir_frozen.xml b/libs/androidfw/tests/data/basic/res/values-vs/values.xml
similarity index 64%
rename from packages/DocumentsUI/res/animator/dir_frozen.xml
rename to libs/androidfw/tests/data/basic/res/values-vs/values.xml
index b541d13..4a5a640 100644
--- a/packages/DocumentsUI/res/animator/dir_frozen.xml
+++ b/libs/androidfw/tests/data/basic/res/values-vs/values.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2013 The Android Open Source Project
+<?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.
@@ -13,9 +14,6 @@
      limitations under the License.
 -->
 
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:valueFrom="0"
-    android:valueTo="0"
-    android:propertyName="position"
-    android:valueType="floatType"
-    android:duration="@android:integer/config_mediumAnimTime" />
+<resources>
+    <integer name="number1">600</integer>
+</resources>
diff --git a/libs/androidfw/tests/data/basic/split_de_fr_arsc.h b/libs/androidfw/tests/data/basic/split_de_fr_arsc.h
index b742d28..a2aa598 100644
--- a/libs/androidfw/tests/data/basic/split_de_fr_arsc.h
+++ b/libs/androidfw/tests/data/basic/split_de_fr_arsc.h
@@ -1,5 +1,5 @@
 unsigned char split_de_fr_arsc[] = {
-  0x02, 0x00, 0x0c, 0x00, 0xe4, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x0c, 0x00, 0xf4, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
@@ -10,7 +10,7 @@
   0x32, 0x00, 0x00, 0x00, 0x07, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00,
   0x61, 0x00, 0x69, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00,
   0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x20, 0x00,
-  0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x5c, 0x03, 0x00, 0x00,
+  0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x6c, 0x03, 0x00, 0x00,
   0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
   0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
   0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
@@ -57,30 +57,32 @@
   0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00,
   0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
-  0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-  0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
+  0x78, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00,
+  0x78, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x66, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
-  0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00,
-  0x01, 0x02, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x66, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
-  0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  0x00, 0x00, 0x00, 0x00, 0x4c, 0x61, 0x74, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00
 };
-unsigned int split_de_fr_arsc_len = 996;
+unsigned int split_de_fr_arsc_len = 1012;
diff --git a/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h
index e9fb7ea..0cc3915 100644
--- a/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h
+++ b/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h
@@ -1,10 +1,10 @@
 unsigned char split_hdpi_v4_arsc[] = {
-  0x02, 0x00, 0x0c, 0x00, 0x08, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x0c, 0x00, 0x10, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x1c, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x68, 0x00,
   0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01,
-  0xd0, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
+  0xd8, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
   0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
   0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00,
   0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00,
@@ -50,19 +50,20 @@
   0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
   0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x02, 0x44, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x01, 0x02, 0x4c, 0x00, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00
 };
-unsigned int split_hdpi_v4_arsc_len = 776;
+unsigned int split_hdpi_v4_arsc_len = 784;
diff --git a/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h
index 7835f71..d44ba96 100644
--- a/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h
+++ b/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h
@@ -1,10 +1,10 @@
 unsigned char split_xhdpi_v4_arsc[] = {
-  0x02, 0x00, 0x0c, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x0c, 0x00, 0x14, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x78, 0x00,
   0x68, 0x00, 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x02, 0x20, 0x01, 0xd0, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x02, 0x20, 0x01, 0xd8, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
   0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00,
   0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00,
   0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00,
@@ -50,19 +50,20 @@
   0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
   0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x60, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x68, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+  0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
-unsigned int split_xhdpi_v4_arsc_len = 780;
+unsigned int split_xhdpi_v4_arsc_len = 788;
diff --git a/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h
index f805db1..2f3f682 100644
--- a/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h
+++ b/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h
@@ -1,10 +1,10 @@
 unsigned char split_xxhdpi_v4_arsc[] = {
-  0x02, 0x00, 0x0c, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x0c, 0x00, 0x14, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x78, 0x00,
   0x78, 0x00, 0x68, 0x00, 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00,
-  0x00, 0x02, 0x20, 0x01, 0xd0, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x02, 0x20, 0x01, 0xd8, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
   0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00,
   0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00,
   0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00,
@@ -50,19 +50,20 @@
   0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
   0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x60, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x4c, 0x00, 0x68, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+  0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
-unsigned int split_xxhdpi_v4_arsc_len = 780;
+unsigned int split_xxhdpi_v4_arsc_len = 788;
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index cc38af2..ca07738 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -240,6 +240,7 @@
     tests/unit/DamageAccumulatorTests.cpp \
     tests/unit/DeviceInfoTests.cpp \
     tests/unit/FatVectorTests.cpp \
+    tests/unit/GlopBuilderTests.cpp \
     tests/unit/GpuMemoryTrackerTests.cpp \
     tests/unit/LayerUpdateQueueTests.cpp \
     tests/unit/LinearAllocatorTests.cpp \
@@ -253,6 +254,8 @@
 
 ifeq (true, $(HWUI_NEW_OPS))
     LOCAL_SRC_FILES += \
+        tests/unit/BakedOpDispatcherTests.cpp \
+        tests/unit/BakedOpRendererTests.cpp \
         tests/unit/BakedOpStateTests.cpp \
         tests/unit/FrameBuilderTests.cpp \
         tests/unit/LeakCheckTests.cpp \
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index 98493d7..bb3ea3f 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -40,6 +40,16 @@
 void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) {
     LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");
 
+    // subtract repaintRect from region, since it will be regenerated
+    if (repaintRect.contains(0, 0,
+                offscreenBuffer->viewportWidth, offscreenBuffer->viewportHeight)) {
+        // repaint full layer, so throw away entire region
+        offscreenBuffer->region.clear();
+    } else {
+        offscreenBuffer->region.subtractSelf(android::Rect(repaintRect.left, repaintRect.top,
+                repaintRect.right, repaintRect.bottom));
+    }
+
     mRenderTarget.offscreenBuffer = offscreenBuffer;
 
     // create and bind framebuffer
@@ -324,7 +334,7 @@
     }
 }
 
-void BakedOpRenderer::renderGlop(const Rect* dirtyBounds, const ClipBase* clip,
+void BakedOpRenderer::renderGlopImpl(const Rect* dirtyBounds, const ClipBase* clip,
         const Glop& glop) {
     prepareRender(dirtyBounds, clip);
     mRenderState.render(glop, mRenderTarget.orthoMatrix);
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
index 4b65255..1b4065a 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_HWUI_BAKED_OP_RENDERER_H
-#define ANDROID_HWUI_BAKED_OP_RENDERER_H
+#pragma once
 
 #include "BakedOpState.h"
 #include "Matrix.h"
@@ -41,6 +40,7 @@
  */
 class BakedOpRenderer {
 public:
+    typedef void (*GlopReceiver)(BakedOpRenderer&, const Rect*, const ClipBase*, const Glop&);
     /**
      * Position agnostic shadow lighting info. Used with all shadow ops in scene.
      */
@@ -54,8 +54,10 @@
         uint8_t spotShadowAlpha;
     };
 
-    BakedOpRenderer(Caches& caches, RenderState& renderState, bool opaque, const LightInfo& lightInfo)
-            : mRenderState(renderState)
+    BakedOpRenderer(Caches& caches, RenderState& renderState, bool opaque,
+            const LightInfo& lightInfo)
+            : mGlopReceiver(DefaultGlopReceiver)
+            , mRenderState(renderState)
             , mCaches(caches)
             , mOpaque(opaque)
             , mLightInfo(lightInfo) {
@@ -81,7 +83,9 @@
     }
     void renderFunctor(const FunctorOp& op, const BakedOpState& state);
 
-    void renderGlop(const Rect* dirtyBounds, const ClipBase* clip, const Glop& glop);
+    void renderGlop(const Rect* dirtyBounds, const ClipBase* clip, const Glop& glop) {
+        mGlopReceiver(*this, dirtyBounds, clip, glop);
+    }
     bool offscreenRenderTarget() { return mRenderTarget.offscreenBuffer != nullptr; }
     void dirtyRenderTarget(const Rect& dirtyRect);
     bool didDraw() const { return mHasDrawn; }
@@ -95,7 +99,14 @@
         drawRects(ltrb, 4, paint);
     }
     void drawRects(const float* rects, int count, const SkPaint* paint);
+protected:
+    GlopReceiver mGlopReceiver;
 private:
+    static void DefaultGlopReceiver(BakedOpRenderer& renderer, const Rect* dirtyBounds,
+            const ClipBase* clip, const Glop& glop) {
+        renderer.renderGlopImpl(dirtyBounds, clip, glop);
+    }
+    void renderGlopImpl(const Rect* dirtyBounds, const ClipBase* clip, const Glop& glop);
     void setViewport(uint32_t width, uint32_t height);
     void clearColorBuffer(const Rect& clearRect);
     void prepareRender(const Rect* dirtyBounds, const ClipBase* clip);
@@ -136,5 +147,3 @@
 
 }; // namespace uirenderer
 }; // namespace android
-
-#endif // ANDROID_HWUI_BAKED_OP_RENDERER_H
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index afe9807..f886dda 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -41,6 +41,10 @@
     return transformedBounds;
 }
 
+void ClipBase::dump() const {
+    ALOGD("mode %d" RECT_STRING, mode, RECT_ARGS(rect));
+}
+
 /*
  * TransformedRectangle
  */
diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h
index 479796d..1654eb8 100644
--- a/libs/hwui/ClipArea.h
+++ b/libs/hwui/ClipArea.h
@@ -106,6 +106,8 @@
     // Bounds of the clipping area, used to define the scissor, and define which
     // portion of the stencil is updated/used
     Rect rect;
+
+    void dump() const;
 };
 
 struct ClipRect : ClipBase {
diff --git a/libs/hwui/FloatColor.h b/libs/hwui/FloatColor.h
index 97dec88..9a39ec2 100644
--- a/libs/hwui/FloatColor.h
+++ b/libs/hwui/FloatColor.h
@@ -17,6 +17,7 @@
 #define FLOATCOLOR_H
 
 #include "utils/Macros.h"
+#include "utils/MathUtils.h"
 
 #include <stdint.h>
 
@@ -38,6 +39,17 @@
                 || b > 0.0f;
     }
 
+    bool operator==(const FloatColor& other) const {
+        return MathUtils::areEqual(r, other.r)
+                && MathUtils::areEqual(g, other.g)
+                && MathUtils::areEqual(b, other.b)
+                && MathUtils::areEqual(a, other.a);
+    }
+
+    bool operator!=(const FloatColor& other) const {
+        return !(*this == other);
+    }
+
     float r;
     float g;
     float b;
diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h
index e72f396..704bd69 100644
--- a/libs/hwui/Glop.h
+++ b/libs/hwui/Glop.h
@@ -81,8 +81,10 @@
  * vertex/index/Texture/RoundRectClipState pointers prevent this from
  * being safe.
  */
-// TODO: PREVENT_COPY_AND_ASSIGN(...) or similar
 struct Glop {
+    PREVENT_COPY_AND_ASSIGN(Glop);
+public:
+    Glop() { }
     struct Mesh {
         GLuint primitiveMode; // GL_TRIANGLES and GL_TRIANGLE_STRIP supported
 
@@ -149,7 +151,7 @@
        }
     } transform;
 
-    const RoundRectClipState* roundRectClipState;
+    const RoundRectClipState* roundRectClipState = nullptr;
 
     /**
      * Blending to be used by this draw - both GL_NONE if blending is disabled.
@@ -165,7 +167,7 @@
      * Bounds of the drawing command in layer space. Only mapped into layer
      * space once GlopBuilder::build() is called.
      */
-    Rect bounds;
+    Rect bounds; // TODO: remove for HWUI_NEW_OPS
 
     /**
      * Additional render state to enumerate:
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 45fc16c..2799def 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -676,8 +676,11 @@
             fill.skiaShaderData.skiaShaderType);
 
     ALOGD("Glop transform");
-    glop.transform.modelView.dump("model view");
-    glop.transform.canvas.dump("canvas");
+    glop.transform.modelView.dump("  model view");
+    glop.transform.canvas.dump("  canvas");
+    ALOGD_IF(glop.transform.transformFlags, "  transformFlags 0x%x", glop.transform.transformFlags);
+
+    ALOGD_IF(glop.roundRectClipState, "Glop RRCS %p", glop.roundRectClipState);
 
     ALOGD("Glop blend %d %d", glop.blend.src, glop.blend.dst);
     ALOGD("Glop bounds " RECT_STRING, RECT_ARGS(glop.bounds));
diff --git a/libs/hwui/LayerBuilder.cpp b/libs/hwui/LayerBuilder.cpp
index c5af279..e6a95ff 100644
--- a/libs/hwui/LayerBuilder.cpp
+++ b/libs/hwui/LayerBuilder.cpp
@@ -349,8 +349,9 @@
 }
 
 void LayerBuilder::dump() const {
-    ALOGD("LayerBuilder %p, %ux%u buffer %p, blo %p, rn %p",
-            this, width, height, offscreenBuffer, beginLayerOp, renderNode);
+    ALOGD("LayerBuilder %p, %ux%u buffer %p, blo %p, rn %p (%s)",
+            this, width, height, offscreenBuffer, beginLayerOp,
+            renderNode, renderNode ? renderNode->getName() : "-");
     for (const BatchBase* batch : mBatches) {
         batch->dump();
     }
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index deab956..709156c 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -437,8 +437,16 @@
     y = dy * dz;
 }
 
+/**
+ * Set the contents of the rect to be the bounding rect around each of the corners, mapped by the
+ * matrix.
+ *
+ * NOTE: an empty rect to an arbitrary matrix isn't guaranteed to have an empty output, since that's
+ * important for conservative bounds estimation (e.g. rotate45Matrix.mapRect of Rect(0, 10) should
+ * result in non-empty.
+ */
 void Matrix4::mapRect(Rect& r) const {
-    if (isIdentity() || r.isEmpty()) return;
+    if (isIdentity()) return;
 
     if (isSimple()) {
         MUL_ADD_STORE(r.left, data[kScaleX], data[kTranslateX]);
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index ddf0528..11eb825 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -24,8 +24,8 @@
 namespace android {
 namespace uirenderer {
 
-
-static Rect sUnreasonablyLargeBounds(-10000, -10000, 10000, 10000);
+#define MIL_PIX 1000000
+static Rect sUnreasonablyLargeBounds(-MIL_PIX, -MIL_PIX, MIL_PIX, MIL_PIX);
 
 static const Rect& getConservativeOpBounds(const ClipBase* clip) {
     // if op is clipped, that rect can be used, but otherwise just use a conservatively large rect
@@ -356,11 +356,15 @@
 }
 void RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom,
             float rx, float ry, const SkPaint& paint) {
-    addOp(alloc().create_trivial<RoundRectOp>(
-            Rect(left, top, right, bottom),
-            *(mState.currentSnapshot()->transform),
-            getRecordedClip(),
-            refPaint(&paint), rx, ry));
+    if (CC_LIKELY(MathUtils::isPositive(rx) || MathUtils::isPositive(ry))) {
+        addOp(alloc().create_trivial<RoundRectOp>(
+                Rect(left, top, right, bottom),
+                *(mState.currentSnapshot()->transform),
+                getRecordedClip(),
+                refPaint(&paint), rx, ry));
+    } else {
+        drawRect(left, top, right, bottom, paint);
+    }
 }
 
 void RecordingCanvas::drawRoundRect(
@@ -564,15 +568,17 @@
             getRecordedClip(),
             renderNode);
     int opIndex = addOp(op);
-    int childIndex = mDisplayList->addChild(op);
+    if (CC_LIKELY(opIndex >= 0)) {
+        int childIndex = mDisplayList->addChild(op);
 
-    // update the chunk's child indices
-    DisplayList::Chunk& chunk = mDisplayList->chunks.back();
-    chunk.endChildIndex = childIndex + 1;
+        // update the chunk's child indices
+        DisplayList::Chunk& chunk = mDisplayList->chunks.back();
+        chunk.endChildIndex = childIndex + 1;
 
-    if (renderNode->stagingProperties().isProjectionReceiver()) {
-        // use staging property, since recording on UI thread
-        mDisplayList->projectionReceiveIndex = opIndex;
+        if (renderNode->stagingProperties().isProjectionReceiver()) {
+            // use staging property, since recording on UI thread
+            mDisplayList->projectionReceiveIndex = opIndex;
+        }
     }
 }
 
@@ -595,7 +601,7 @@
     mDisplayList->functors.push_back(functor);
     auto clip = getRecordedClip();
     addOp(alloc().create_trivial<FunctorOp>(
-            getConservativeOpBounds(clip), // TODO: explicitly define bounds
+            getConservativeOpBounds(clip),
             *(mState.currentSnapshot()->transform),
             clip,
             functor));
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index d9fce9b..de4fa55 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -286,7 +286,8 @@
 
     friend std::ostream& operator<<(std::ostream& os, const Rect& rect) {
         if (rect.isEmpty()) {
-            return os << "empty";
+            // Print empty, but continue, since empty rects may still have useful coordinate info
+            os << "(empty)";
         }
 
         if (rect.left == 0 && rect.top == 0) {
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index 2e3856f..d35f764 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -158,7 +158,8 @@
 
 void FullPath::updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha,
         SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd,
-        float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin) {
+        float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin,
+        int fillType) {
     mProperties.strokeWidth = strokeWidth;
     mProperties.strokeColor = strokeColor;
     mProperties.strokeAlpha = strokeAlpha;
@@ -167,6 +168,7 @@
     mProperties.strokeMiterLimit = strokeMiterLimit;
     mProperties.strokeLineCap = strokeLineCap;
     mProperties.strokeLineJoin = strokeLineJoin;
+    mProperties.fillType = fillType;
 
     // If any trim property changes, mark trim dirty and update the trim path
     setTrimPathStart(trimPathStart);
@@ -179,7 +181,7 @@
     return SkColorSetA(color, alphaBytes * alpha);
 }
 
-void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float strokeScale,
+void FullPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeScale,
                         const SkMatrix& matrix){
     // Draw path's fill, if fill color or gradient is valid
     bool needsFill = false;
@@ -196,6 +198,8 @@
     if (needsFill) {
         mPaint.setStyle(SkPaint::Style::kFill_Style);
         mPaint.setAntiAlias(true);
+        SkPath::FillType ft = static_cast<SkPath::FillType>(mProperties.fillType);
+        renderPath.setFillType(ft);
         outCanvas->drawPath(renderPath, mPaint);
     }
 
@@ -229,19 +233,25 @@
         // No trimming necessary.
         return;
     }
+    mTrimDirty = false;
+    mTrimmedSkPath.reset();
+    if (mProperties.trimPathStart == mProperties.trimPathEnd) {
+        // Trimmed path should be empty.
+        return;
+    }
     SkPathMeasure measure(mSkPath, false);
     float len = SkScalarToFloat(measure.getLength());
     float start = len * fmod((mProperties.trimPathStart + mProperties.trimPathOffset), 1.0f);
     float end = len * fmod((mProperties.trimPathEnd + mProperties.trimPathOffset), 1.0f);
 
-    mTrimmedSkPath.reset();
     if (start > end) {
         measure.getSegment(start, len, &mTrimmedSkPath, true);
-        measure.getSegment(0, end, &mTrimmedSkPath, true);
+        if (end > 0) {
+            measure.getSegment(0, end, &mTrimmedSkPath, true);
+        }
     } else {
         measure.getSegment(start, end, &mTrimmedSkPath, true);
     }
-    mTrimDirty = false;
 }
 
 REQUIRE_COMPATIBLE_LAYOUT(FullPath::Properties);
@@ -300,7 +310,7 @@
     }
 }
 
-void ClipPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
+void ClipPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath,
         float strokeScale, const SkMatrix& matrix){
     outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op);
 }
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index 36a8aeb..4d2fed0 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -96,7 +96,7 @@
 
 protected:
     virtual const SkPath& getUpdatedPath();
-    virtual void drawPath(SkCanvas *outCanvas, const SkPath& renderPath,
+    virtual void drawPath(SkCanvas *outCanvas, SkPath& renderPath,
             float strokeScale, const SkMatrix& matrix) = 0;
     Data mData;
     SkPath mSkPath;
@@ -118,6 +118,7 @@
     int32_t strokeLineCap = SkPaint::Cap::kButt_Cap;
     int32_t strokeLineJoin = SkPaint::Join::kMiter_Join;
     float strokeMiterLimit = 4;
+    int fillType = 0; /* non-zero or kWinding_FillType in Skia */
 };
 
     FullPath(const FullPath& path); // for cloning
@@ -133,7 +134,7 @@
     void updateProperties(float strokeWidth, SkColor strokeColor,
             float strokeAlpha, SkColor fillColor, float fillAlpha,
             float trimPathStart, float trimPathEnd, float trimPathOffset,
-            float strokeMiterLimit, int strokeLineCap, int strokeLineJoin);
+            float strokeMiterLimit, int strokeLineCap, int strokeLineJoin, int fillType);
     // TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI
     float getStrokeWidth() {
         return mProperties.strokeWidth;
@@ -197,7 +198,7 @@
 
 protected:
     const SkPath& getUpdatedPath() override;
-    void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
+    void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
             float strokeScale, const SkMatrix& matrix) override;
 
 private:
@@ -213,6 +214,7 @@
         StrokeLineCap,
         StrokeLineJoin,
         StrokeMiterLimit,
+        FillType,
         Count,
     };
     // Applies trimming to the specified path.
@@ -233,7 +235,7 @@
     ClipPath(const Data& nodes) : Path(nodes) {}
 
 protected:
-    void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
+    void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
             float strokeScale, const SkMatrix& matrix) override;
 };
 
diff --git a/libs/hwui/debug/nullgles.cpp b/libs/hwui/debug/nullgles.cpp
index ffb0649..8689f98 100644
--- a/libs/hwui/debug/nullgles.cpp
+++ b/libs/hwui/debug/nullgles.cpp
@@ -133,6 +133,15 @@
     }
 }
 
+GLenum glCheckFramebufferStatus(GLenum target) {
+    switch (target) {
+    case GL_FRAMEBUFFER:
+        return GL_FRAMEBUFFER_COMPLETE;
+    default:
+        return 0; // error case
+    }
+}
+
 const char* getString(GLenum name) {
     switch (name) {
     case GL_VENDOR:
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp
index 5f984b5..bb1a044 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.cpp
+++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp
@@ -164,6 +164,9 @@
         // resize in place
         layer->viewportWidth = width;
         layer->viewportHeight = height;
+
+        // entire area will be repainted (and may be smaller) so clear usage region
+        layer->region.clear();
         return layer;
     }
     putOrDelete(layer);
diff --git a/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp b/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
new file mode 100644
index 0000000..654ddc6
--- /dev/null
+++ b/libs/hwui/tests/unit/BakedOpDispatcherTests.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 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 <gtest/gtest.h>
+
+#include <RecordedOp.h>
+#include <BakedOpDispatcher.h>
+#include <BakedOpRenderer.h>
+#include <tests/common/TestUtils.h>
+
+using namespace android::uirenderer;
+
+static BakedOpRenderer::LightInfo sLightInfo;
+static Rect sBaseClip(100, 100);
+
+class ValidatingBakedOpRenderer : public BakedOpRenderer {
+public:
+    ValidatingBakedOpRenderer(RenderState& renderState, std::function<void(const Glop& glop)> validator)
+            : BakedOpRenderer(Caches::getInstance(), renderState, true, sLightInfo)
+            , mValidator(validator) {
+        mGlopReceiver = ValidatingGlopReceiver;
+    }
+private:
+    static void ValidatingGlopReceiver(BakedOpRenderer& renderer, const Rect* dirtyBounds,
+            const ClipBase* clip, const Glop& glop) {
+
+        auto vbor = reinterpret_cast<ValidatingBakedOpRenderer*>(&renderer);
+        vbor->mValidator(glop);
+    }
+    std::function<void(const Glop& glop)> mValidator;
+};
+
+typedef void (*BakedOpReceiver)(BakedOpRenderer&, const BakedOpState&);
+
+static void testUnmergedGlopDispatch(renderthread::RenderThread& renderThread, RecordedOp* op,
+        std::function<void(const Glop& glop)> glopVerifier) {
+    // Create op, and wrap with basic state.
+    LinearAllocator allocator;
+    auto snapshot = TestUtils::makeSnapshot(Matrix4::identity(), sBaseClip);
+    auto state = BakedOpState::tryConstruct(allocator, *snapshot, *op);
+    ASSERT_NE(nullptr, state);
+
+    int glopCount = 0;
+    auto glopReceiver = [&glopVerifier, &glopCount] (const Glop& glop) {
+        ASSERT_EQ(glopCount++, 0) << "Only one Glop expected";
+        glopVerifier(glop);
+    };
+    ValidatingBakedOpRenderer renderer(renderThread.renderState(), glopReceiver);
+
+    // Dispatch based on op type created, similar to Frame/LayerBuilder dispatch behavior
+#define X(Type) \
+        [](BakedOpRenderer& renderer, const BakedOpState& state) { \
+            BakedOpDispatcher::on##Type(renderer, static_cast<const Type&>(*(state.op)), state); \
+        },
+    static BakedOpReceiver unmergedReceivers[] = BUILD_RENDERABLE_OP_LUT(X);
+#undef X
+    unmergedReceivers[op->opId](renderer, *state);
+    ASSERT_EQ(1, glopCount) << "Exactly one Glop expected";
+}
+
+RENDERTHREAD_TEST(BakedOpDispatcher, onArc_position) {
+    SkPaint strokePaint;
+    strokePaint.setStyle(SkPaint::kStroke_Style);
+    strokePaint.setStrokeWidth(4);
+    ArcOp op(Rect(10, 15, 20, 25), Matrix4::identity(), nullptr, &strokePaint, 0, 270, true);
+    testUnmergedGlopDispatch(renderThread, &op, [] (const Glop& glop) {
+        // validate glop produced by renderPathTexture (so texture, unit quad)
+        auto texture = glop.fill.texture.texture;
+        ASSERT_NE(nullptr, texture);
+        float expectedOffset = floor(4 * 1.5f + 0.5f);
+        EXPECT_EQ(expectedOffset, reinterpret_cast<PathTexture*>(texture)->offset)
+                << "Should see conservative offset from PathCache::computeBounds";
+        Rect expectedBounds(10, 15, 20, 25);
+        expectedBounds.outset(expectedOffset);
+        EXPECT_EQ(expectedBounds, glop.bounds) << "bounds outset by stroke 'offset'";
+        Matrix4 expectedModelView;
+        expectedModelView.loadTranslate(10 - expectedOffset, 15 - expectedOffset, 0);
+        expectedModelView.scale(10 + 2 * expectedOffset, 10 + 2 * expectedOffset, 1);
+        EXPECT_EQ(expectedModelView, glop.transform.modelView)
+                << "X and Y offsets, and scale both applied to model view";
+    });
+}
+
+RENDERTHREAD_TEST(BakedOpDispatcher, onLayerOp_bufferless) {
+    SkPaint layerPaint;
+    layerPaint.setAlpha(128);
+    OffscreenBuffer* buffer = nullptr; // no providing a buffer, should hit rect fallback case
+    LayerOp op(Rect(10, 10), Matrix4::identity(), nullptr, &layerPaint, &buffer);
+    testUnmergedGlopDispatch(renderThread, &op, [&renderThread] (const Glop& glop) {
+        // rect glop is dispatched with paint props applied
+        EXPECT_EQ(renderThread.renderState().meshState().getUnitQuadVBO(),
+                glop.mesh.vertices.bufferObject) << "Unit quad should be drawn";
+        EXPECT_EQ(nullptr, glop.fill.texture.texture) << "Should be no texture when layer is null";
+        EXPECT_FLOAT_EQ(128 / 255.0f, glop.fill.color.a) << "Rect quad should use op alpha";
+    });
+}
diff --git a/libs/hwui/tests/unit/BakedOpRendererTests.cpp b/libs/hwui/tests/unit/BakedOpRendererTests.cpp
new file mode 100644
index 0000000..59bd75e
--- /dev/null
+++ b/libs/hwui/tests/unit/BakedOpRendererTests.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 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 <gtest/gtest.h>
+
+#include <BakedOpRenderer.h>
+#include <tests/common/TestUtils.h>
+
+using namespace android::uirenderer;
+
+const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 };
+
+RENDERTHREAD_TEST(BakedOpRenderer, startRepaintLayer_clear) {
+    BakedOpRenderer renderer(Caches::getInstance(), renderThread.renderState(), true, sLightInfo);
+    OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200u, 200u);
+
+    layer.dirty(Rect(200, 200));
+    {
+        renderer.startRepaintLayer(&layer, Rect(200, 200));
+        EXPECT_TRUE(layer.region.isEmpty()) << "Repaint full layer should clear region";
+        renderer.endLayer();
+    }
+
+    layer.dirty(Rect(200, 200));
+    {
+        renderer.startRepaintLayer(&layer, Rect(100, 200)); // repainting left side
+        EXPECT_TRUE(layer.region.isRect());
+        //ALOGD("bounds %d %d %d %d", RECT_ARGS(layer.region.getBounds()));
+        EXPECT_EQ(android::Rect(100, 0, 200, 200), layer.region.getBounds())
+                << "Left side being repainted, so right side should be clear";
+        renderer.endLayer();
+    }
+
+    // right side is now only dirty portion
+    {
+        renderer.startRepaintLayer(&layer, Rect(100, 0, 200, 200)); // repainting right side
+        EXPECT_TRUE(layer.region.isEmpty())
+                << "Now right side being repainted, so region should be entirely clear";
+        renderer.endLayer();
+    }
+}
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 4c56a22..f147fd4 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -349,6 +349,29 @@
     EXPECT_EQ(1, renderer.getIndex());
 }
 
+TEST(FrameBuilder, functor_reject) {
+    class FunctorTestRenderer : public TestRendererBase {
+    public:
+        void onFunctorOp(const FunctorOp& op, const BakedOpState& state) override {
+            EXPECT_EQ(0, mIndex++);
+        }
+    };
+    Functor noopFunctor;
+
+    // 1 million pixel tall view, scrolled down 80%
+    auto scrolledFunctorView = TestUtils::createNode(0, 0, 400, 1000000,
+            [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) {
+        canvas.translate(0, -800000);
+        canvas.callDrawGLFunction(&noopFunctor);
+    });
+
+    FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
+            TestUtils::createSyncedNodeList(scrolledFunctorView), sLightGeometry, nullptr);
+    FunctorTestRenderer renderer;
+    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(1, renderer.getIndex()) << "Functor should not be rejected";
+}
+
 TEST(FrameBuilder, renderNode) {
     class RenderNodeTestRenderer : public TestRendererBase {
     public:
@@ -391,6 +414,7 @@
             TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
     RenderNodeTestRenderer renderer;
     frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    EXPECT_EQ(2, renderer.getIndex());
 }
 
 TEST(FrameBuilder, clipped) {
diff --git a/libs/hwui/tests/unit/GlopBuilderTests.cpp b/libs/hwui/tests/unit/GlopBuilderTests.cpp
new file mode 100644
index 0000000..454011f
--- /dev/null
+++ b/libs/hwui/tests/unit/GlopBuilderTests.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2016 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 <gtest/gtest.h>
+
+#include "Glop.h"
+#include "GlopBuilder.h"
+#include "Rect.h"
+#include "tests/common/TestUtils.h"
+#include "utils/Color.h"
+
+#include <SkPaint.h>
+
+using namespace android::uirenderer;
+
+static void expectFillEq(Glop::Fill& expectedFill, Glop::Fill& builtFill) {
+    EXPECT_EQ(expectedFill.colorEnabled, builtFill.colorEnabled);
+    if (expectedFill.colorEnabled)
+        EXPECT_EQ(expectedFill.color, builtFill.color);
+
+    EXPECT_EQ(expectedFill.filterMode, builtFill.filterMode);
+    if (expectedFill.filterMode == ProgramDescription::ColorFilterMode::Blend) {
+        EXPECT_EQ(expectedFill.filter.color, builtFill.filter.color);
+    } else if (expectedFill.filterMode == ProgramDescription::ColorFilterMode::Matrix) {
+        Glop::Fill::Filter::Matrix& expectedMatrix = expectedFill.filter.matrix;
+        Glop::Fill::Filter::Matrix& builtMatrix = expectedFill.filter.matrix;
+        EXPECT_TRUE(std::memcmp(expectedMatrix.matrix, builtMatrix.matrix,
+                sizeof(Glop::Fill::Filter::Matrix::matrix)));
+        EXPECT_TRUE(std::memcmp(expectedMatrix.vector, builtMatrix.vector,
+                sizeof(Glop::Fill::Filter::Matrix::vector)));
+    }
+    EXPECT_EQ(expectedFill.skiaShaderData.skiaShaderType, builtFill.skiaShaderData.skiaShaderType);
+    EXPECT_EQ(expectedFill.texture.clamp, builtFill.texture.clamp);
+    EXPECT_EQ(expectedFill.texture.filter, builtFill.texture.filter);
+    EXPECT_EQ(expectedFill.texture.target, builtFill.texture.target);
+    EXPECT_EQ(expectedFill.texture.textureTransform, builtFill.texture.textureTransform);
+}
+
+static void expectBlendEq(Glop::Blend& expectedBlend, Glop::Blend& builtBlend) {
+    EXPECT_EQ(expectedBlend.src, builtBlend.src);
+    EXPECT_EQ(expectedBlend.dst, builtBlend.dst);
+}
+
+static void expectMeshEq(Glop::Mesh& expectedMesh, Glop::Mesh& builtMesh) {
+    EXPECT_EQ(expectedMesh.elementCount, builtMesh.elementCount);
+    EXPECT_EQ(expectedMesh.primitiveMode, builtMesh.primitiveMode);
+    EXPECT_EQ(expectedMesh.indices.indices, builtMesh.indices.indices);
+    EXPECT_EQ(expectedMesh.indices.bufferObject, builtMesh.indices.bufferObject);
+    EXPECT_EQ(expectedMesh.vertices.attribFlags, builtMesh.vertices.attribFlags);
+    EXPECT_EQ(expectedMesh.vertices.bufferObject, builtMesh.vertices.bufferObject);
+    EXPECT_EQ(expectedMesh.vertices.color, builtMesh.vertices.color);
+    EXPECT_EQ(expectedMesh.vertices.position, builtMesh.vertices.position);
+    EXPECT_EQ(expectedMesh.vertices.stride, builtMesh.vertices.stride);
+    EXPECT_EQ(expectedMesh.vertices.texCoord, builtMesh.vertices.texCoord);
+
+    if (builtMesh.vertices.position) {
+        for (int i = 0; i < 4; i++) {
+            TextureVertex& expectedVertex = expectedMesh.mappedVertices[i];
+            TextureVertex& builtVertex = builtMesh.mappedVertices[i];
+            EXPECT_EQ(expectedVertex.u, builtVertex.u);
+            EXPECT_EQ(expectedVertex.v, builtVertex.v);
+            EXPECT_EQ(expectedVertex.x, builtVertex.x);
+            EXPECT_EQ(expectedVertex.y, builtVertex.y);
+        }
+    }
+}
+
+static void expectTransformEq(Glop::Transform& expectedTransform, Glop::Transform& builtTransform) {
+    EXPECT_EQ(expectedTransform.canvas, builtTransform.canvas);
+    EXPECT_EQ(expectedTransform.modelView, builtTransform.modelView);
+    EXPECT_EQ(expectedTransform.transformFlags, expectedTransform.transformFlags);
+}
+
+static void expectGlopEq(Glop& expectedGlop, Glop& builtGlop) {
+    EXPECT_EQ(expectedGlop.bounds, builtGlop.bounds);
+    expectBlendEq(expectedGlop.blend, builtGlop.blend);
+    expectFillEq(expectedGlop.fill, builtGlop.fill);
+    expectMeshEq(expectedGlop.mesh, builtGlop.mesh);
+    expectTransformEq(expectedGlop.transform, builtGlop.transform);
+}
+
+static std::unique_ptr<Glop> blackUnitQuadGlop(RenderState& renderState) {
+    std::unique_ptr<Glop> glop(new Glop());
+    glop->blend = { GL_ZERO, GL_ZERO };
+    glop->mesh.elementCount = 4;
+    glop->mesh.primitiveMode = GL_TRIANGLE_STRIP;
+    glop->mesh.indices.indices = nullptr;
+    glop->mesh.indices.bufferObject = GL_ZERO;
+    glop->mesh.vertices = {
+            renderState.meshState().getUnitQuadVBO(),
+            VertexAttribFlags::None,
+            nullptr, nullptr, nullptr,
+            kTextureVertexStride };
+    glop->transform.modelView.loadIdentity();
+    glop->fill.colorEnabled = true;
+    glop->fill.color.set(Color::Black);
+    glop->fill.skiaShaderData.skiaShaderType = kNone_SkiaShaderType;
+    glop->fill.filterMode = ProgramDescription::ColorFilterMode::None;
+    glop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
+    return glop;
+}
+
+RENDERTHREAD_TEST(GlopBuilder, rectSnapTest) {
+    RenderState& renderState = renderThread.renderState();
+    Caches& caches = Caches::getInstance();
+    SkPaint paint;
+    Rect dest(1, 1, 100, 100);
+    Matrix4 simpleTranslate;
+    simpleTranslate.loadTranslate(0.7, 0.7, 0);
+    Glop glop;
+    GlopBuilder(renderState, caches, &glop)
+            .setRoundRectClipState(nullptr)
+            .setMeshUnitQuad()
+            .setFillPaint(paint, 1.0f)
+            .setTransform(simpleTranslate, TransformFlags::None)
+            .setModelViewMapUnitToRectSnap(dest)
+            .build();
+
+    std::unique_ptr<Glop> goldenGlop(blackUnitQuadGlop(renderState));
+    // Rect(1,1,100,100) is the set destination,
+    // so unit quad should be translated by (1,1) and scaled by (99, 99)
+    // Tricky part: because translate (0.7, 0.7) and snapping were set in glopBuilder,
+    // unit quad also should be translate by additional (0.3, 0.3) to snap to exact pixels.
+    goldenGlop->transform.modelView.loadTranslate(1.3, 1.3, 0);
+    goldenGlop->transform.modelView.scale(99, 99, 1);
+    goldenGlop->bounds = android::uirenderer::Rect(1.70, 1.70, 100.70, 100.70);
+    goldenGlop->transform.canvas = simpleTranslate;
+    goldenGlop->fill.texture.filter = GL_NEAREST;
+    expectGlopEq(*goldenGlop, glop);
+}
diff --git a/libs/hwui/tests/unit/LinearAllocatorTests.cpp b/libs/hwui/tests/unit/LinearAllocatorTests.cpp
index 402a09c..ffcbf12 100644
--- a/libs/hwui/tests/unit/LinearAllocatorTests.cpp
+++ b/libs/hwui/tests/unit/LinearAllocatorTests.cpp
@@ -113,3 +113,21 @@
     EXPECT_GT(lastLocation + 20, &v[0]);
 
 }
+
+TEST(LsaVector, dtorCheck) {
+    LinearAllocator allocator;
+    LinearStdAllocator<void*> stdAllocator(allocator);
+
+    for (int size : {1, 2, 3, 500}) {
+        int destroyed = 0;
+        {
+            LsaVector<std::unique_ptr<TestUtils::SignalingDtor> > vector(stdAllocator);
+            for (int i = 0; i < size; i++) {
+                vector.emplace_back(new TestUtils::SignalingDtor(&destroyed));
+            }
+            EXPECT_EQ(0, destroyed);
+            EXPECT_EQ(size, (int) vector.size());
+        }
+        EXPECT_EQ(size, destroyed);
+    }
+}
diff --git a/libs/hwui/tests/unit/MatrixTests.cpp b/libs/hwui/tests/unit/MatrixTests.cpp
index da22637..eddab87 100644
--- a/libs/hwui/tests/unit/MatrixTests.cpp
+++ b/libs/hwui/tests/unit/MatrixTests.cpp
@@ -21,15 +21,30 @@
 
 using namespace android::uirenderer;
 
-TEST(Matrix, mapRect) {
+TEST(Matrix, mapRect_emptyScaleSkew) {
     // Skew, so we don't hit identity/translate/simple fast paths
-    Matrix4 matrix;
-    matrix.skew(0.1f, 0.1f);
+    Matrix4 scaleMatrix;
+    scaleMatrix.loadScale(10, 10, 1);
+    scaleMatrix.skew(0.1f, 0.1f);
 
     // non-zero empty rect, so sorting x/y would make rect non-empty
-    Rect empty(100, 100, -100, -100);
+    Rect empty(15, 20, 15, 100);
     ASSERT_TRUE(empty.isEmpty());
-    matrix.mapRect(empty);
-    EXPECT_TRUE(empty.isEmpty())
-        << "Empty rect should always remain empty, regardless of mapping.";
+    scaleMatrix.mapRect(empty);
+    EXPECT_EQ(Rect(170, 215, 250, 1015), empty);
+    EXPECT_FALSE(empty.isEmpty())
+        << "Empty 'line' rect doesn't remain empty when skewed.";
+}
+
+TEST(Matrix, mapRect_emptyRotate) {
+    // Skew, so we don't hit identity/translate/simple fast paths
+    Matrix4 skewMatrix;
+    skewMatrix.loadRotate(45);
+
+    // non-zero empty rect, so sorting x/y would make rect non-empty
+    Rect lineRect(0, 100);
+    ASSERT_TRUE(lineRect.isEmpty());
+    skewMatrix.mapRect(lineRect);
+    EXPECT_FALSE(lineRect.isEmpty())
+        << "Empty 'line' rect doesn't remain empty when rotated.";
 }
diff --git a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
index 0c6eb57..37a485e 100644
--- a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
+++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
@@ -103,9 +103,11 @@
         OffscreenBufferPool pool;
 
         auto layer = pool.get(thread.renderState(), 64u, 64u);
+        layer->dirty(Rect(64, 64));
 
         // resize in place
         ASSERT_EQ(layer, pool.resize(layer, 60u, 55u));
+        EXPECT_TRUE(layer->region.isEmpty()) << "In place resize should clear usage region";
         EXPECT_EQ(60u, layer->viewportWidth);
         EXPECT_EQ(55u, layer->viewportHeight);
         EXPECT_EQ(64u, layer->texture.width());
@@ -113,9 +115,13 @@
 
         // resized to use different object in pool
         auto layer2 = pool.get(thread.renderState(), 128u, 128u);
+        layer2->dirty(Rect(128, 128));
+        EXPECT_FALSE(layer2->region.isEmpty());
         pool.putOrDelete(layer2);
         ASSERT_EQ(1u, pool.getCount());
+
         ASSERT_EQ(layer2, pool.resize(layer, 120u, 125u));
+        EXPECT_TRUE(layer2->region.isEmpty()) << "Swap resize should clear usage region";
         EXPECT_EQ(120u, layer2->viewportWidth);
         EXPECT_EQ(125u, layer2->viewportHeight);
         EXPECT_EQ(128u, layer2->texture.width());
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index d35b1f9..5e613fd 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -114,6 +114,23 @@
     EXPECT_EQ(Rect(10, 20, 90, 180), op.unmappedBounds);
 }
 
+TEST(RecordingCanvas, drawRoundRect) {
+    // Round case - stays rounded
+    auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+        canvas.drawRoundRect(0, 0, 100, 100, 10, 10, SkPaint());
+    });
+    ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
+    ASSERT_EQ(RecordedOpId::RoundRectOp, dl->getOps()[0]->opId);
+
+    // Non-rounded case - turned into drawRect
+    dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) {
+        canvas.drawRoundRect(0, 0, 100, 100, 0, -1, SkPaint());
+    });
+    ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op";
+    ASSERT_EQ(RecordedOpId::RectOp, dl->getOps()[0]->opId)
+        << "Non-rounded rects should be converted";
+}
+
 TEST(RecordingCanvas, drawText) {
     auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
         SkPaint paint;
@@ -451,6 +468,21 @@
     EXPECT_EQ(3, count);
 }
 
+TEST(RecordingCanvas, drawRenderNode_rejection) {
+    auto child = TestUtils::createNode(50, 50, 150, 150,
+            [](RenderProperties& props, RecordingCanvas& canvas) {
+        SkPaint paint;
+        paint.setColor(SK_ColorWHITE);
+        canvas.drawRect(0, 0, 100, 100, paint);
+    });
+
+    auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [&child](RecordingCanvas& canvas) {
+        canvas.clipRect(0, 0, 0, 0, SkRegion::kIntersect_Op); // empty clip, reject node
+        canvas.drawRenderNode(child.get()); // shouldn't crash when rejecting node...
+    });
+    ASSERT_TRUE(dl->isEmpty());
+}
+
 TEST(RecordingCanvas, drawRenderNode_projection) {
     sp<RenderNode> background = TestUtils::createNode(50, 50, 150, 150,
             [](RenderProperties& props, RecordingCanvas& canvas) {
diff --git a/location/java/android/location/GnssClock.java b/location/java/android/location/GnssClock.java
index 6a7801e..2af4790 100644
--- a/location/java/android/location/GnssClock.java
+++ b/location/java/android/location/GnssClock.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -48,13 +49,19 @@
     private double mDriftUncertaintyNanosPerSecond;
     private int mHardwareClockDiscontinuityCount;
 
-    GnssClock() {
+    /**
+     * @hide
+     */
+    @TestApi
+    public GnssClock() {
         initialize();
     }
 
     /**
      * Sets all contents to the values stored in the provided object.
+     * @hide
      */
+    @TestApi
     public void set(GnssClock clock) {
         mFlags = clock.mFlags;
         mLeapSecond = clock.mLeapSecond;
@@ -70,7 +77,9 @@
 
     /**
      * Resets all the contents to its original state.
+     * @hide
      */
+    @TestApi
     public void reset() {
         initialize();
     }
@@ -95,7 +104,9 @@
 
     /**
      * Sets the leap second associated with the clock's time.
+     * @hide
      */
+    @TestApi
     public void setLeapSecond(int leapSecond) {
         setFlag(HAS_LEAP_SECOND);
         mLeapSecond = leapSecond;
@@ -103,7 +114,9 @@
 
     /**
      * Resets the leap second associated with the clock's time.
+     * @hide
      */
+    @TestApi
     public void resetLeapSecond() {
         resetFlag(HAS_LEAP_SECOND);
         mLeapSecond = Integer.MIN_VALUE;
@@ -129,7 +142,9 @@
 
     /**
      * Sets the GNSS receiver internal clock in nanoseconds.
+     * @hide
      */
+    @TestApi
     public void setTimeNanos(long timeNanos) {
         mTimeNanos = timeNanos;
     }
@@ -153,7 +168,9 @@
 
     /**
      * Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
+     * @hide
      */
+    @TestApi
     public void setTimeUncertaintyNanos(double timeUncertaintyNanos) {
         setFlag(HAS_TIME_UNCERTAINTY);
         mTimeUncertaintyNanos = timeUncertaintyNanos;
@@ -161,7 +178,9 @@
 
     /**
      * Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
+     * @hide
      */
+    @TestApi
     public void resetTimeUncertaintyNanos() {
         resetFlag(HAS_TIME_UNCERTAINTY);
         mTimeUncertaintyNanos = Double.NaN;
@@ -193,7 +212,9 @@
 
     /**
      * Sets the full bias in nanoseconds.
+     * @hide
      */
+    @TestApi
     public void setFullBiasNanos(long value) {
         setFlag(HAS_FULL_BIAS);
         mFullBiasNanos = value;
@@ -201,7 +222,9 @@
 
     /**
      * Resets the full bias in nanoseconds.
+     * @hide
      */
+    @TestApi
     public void resetFullBiasNanos() {
         resetFlag(HAS_FULL_BIAS);
         mFullBiasNanos = Long.MIN_VALUE;
@@ -226,7 +249,9 @@
 
     /**
      * Sets the sub-nanosecond bias.
+     * @hide
      */
+    @TestApi
     public void setBiasNanos(double biasNanos) {
         setFlag(HAS_BIAS);
         mBiasNanos = biasNanos;
@@ -234,7 +259,9 @@
 
     /**
      * Resets the clock's Bias in nanoseconds.
+     * @hide
      */
+    @TestApi
     public void resetBiasNanos() {
         resetFlag(HAS_BIAS);
         mBiasNanos = Double.NaN;
@@ -258,7 +285,9 @@
 
     /**
      * Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
+     * @hide
      */
+    @TestApi
     public void setBiasUncertaintyNanos(double biasUncertaintyNanos) {
         setFlag(HAS_BIAS_UNCERTAINTY);
         mBiasUncertaintyNanos = biasUncertaintyNanos;
@@ -266,7 +295,9 @@
 
     /**
      * Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
+     * @hide
      */
+    @TestApi
     public void resetBiasUncertaintyNanos() {
         resetFlag(HAS_BIAS_UNCERTAINTY);
         mBiasUncertaintyNanos = Double.NaN;
@@ -292,7 +323,9 @@
 
     /**
      * Sets the clock's Drift in nanoseconds per second.
+     * @hide
      */
+    @TestApi
     public void setDriftNanosPerSecond(double driftNanosPerSecond) {
         setFlag(HAS_DRIFT);
         mDriftNanosPerSecond = driftNanosPerSecond;
@@ -300,7 +333,9 @@
 
     /**
      * Resets the clock's Drift in nanoseconds per second.
+     * @hide
      */
+    @TestApi
     public void resetDriftNanosPerSecond() {
         resetFlag(HAS_DRIFT);
         mDriftNanosPerSecond = Double.NaN;
@@ -324,7 +359,9 @@
 
     /**
      * Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
+     * @hide
      */
+    @TestApi
     public void setDriftUncertaintyNanosPerSecond(double driftUncertaintyNanosPerSecond) {
         setFlag(HAS_DRIFT_UNCERTAINTY);
         mDriftUncertaintyNanosPerSecond = driftUncertaintyNanosPerSecond;
@@ -339,14 +376,18 @@
 
     /**
      * Sets count of last hardware clock discontinuity.
+     * @hide
      */
+    @TestApi
     public void setHardwareClockDiscontinuityCount(int value) {
         mHardwareClockDiscontinuityCount = value;
     }
 
     /**
      * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
+     * @hide
      */
+    @TestApi
     public void resetDriftUncertaintyNanosPerSecond() {
         resetFlag(HAS_DRIFT_UNCERTAINTY);
         mDriftUncertaintyNanosPerSecond = Double.NaN;
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index 367c52f..11fecfb 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.annotation.TestApi;
 import android.annotation.IntDef;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -46,6 +47,7 @@
     private double mCarrierPhaseUncertainty;
     private int mMultipathIndicator;
     private double mSnrInDb;
+    private boolean mPseudorangeRateCorrected;
 
     // The following enumerations must be in sync with the values declared in gps.h
 
@@ -55,7 +57,6 @@
     private static final int HAS_CARRIER_CYCLES = (1<<10);
     private static final int HAS_CARRIER_PHASE = (1<<11);
     private static final int HAS_CARRIER_PHASE_UNCERTAINTY = (1<<12);
-    private static final int HAS_UNCORRECTED_PSEUDORANGE_RATE = (1<<18);
 
     /** The status of multipath. */
     @Retention(RetentionPolicy.SOURCE)
@@ -141,13 +142,19 @@
 
     // End enumerations in sync with gps.h
 
-    GnssMeasurement() {
+    /**
+     * @hide
+     */
+    @TestApi
+    public GnssMeasurement() {
         initialize();
     }
 
     /**
      * Sets all contents to the values stored in the provided object.
+     * @hide
      */
+    @TestApi
     public void set(GnssMeasurement measurement) {
         mFlags = measurement.mFlags;
         mSvid = measurement.mSvid;
@@ -174,7 +181,9 @@
 
     /**
      * Resets all the contents to its original state.
+     * @hide
      */
+    @TestApi
     public void reset() {
         initialize();
     }
@@ -189,7 +198,9 @@
 
     /**
      * Sets the Pseud-random number (PRN).
+     * @hide
      */
+    @TestApi
     public void setSvid(int value) {
         mSvid = value;
     }
@@ -204,7 +215,9 @@
 
     /**
      * Sets the constellation type.
+     * @hide
      */
+    @TestApi
     public void setConstellationType(@GnssStatus.ConstellationType int value) {
         mConstellationType = value;
     }
@@ -227,7 +240,9 @@
 
     /**
      * Sets the time offset at which the measurement was taken in nanoseconds.
+     * @hide
      */
+    @TestApi
     public void setTimeOffsetNanos(double value) {
         mTimeOffsetNanos = value;
     }
@@ -244,7 +259,9 @@
 
     /**
      * Sets the sync state.
+     * @hide
      */
+    @TestApi
     public void setState(int value) {
         mState = value;
     }
@@ -353,7 +370,9 @@
 
     /**
      * Sets the received GNSS time in nanoseconds.
+     * @hide
      */
+    @TestApi
     public void setReceivedSvTimeNanos(long value) {
         mReceivedSvTimeNanos = value;
     }
@@ -367,7 +386,9 @@
 
     /**
      * Sets the received GNSS time uncertainty (1-Sigma) in nanoseconds.
+     * @hide
      */
+    @TestApi
     public void setReceivedSvTimeUncertaintyNanos(long value) {
         mReceivedSvTimeUncertaintyNanos = value;
     }
@@ -384,7 +405,9 @@
 
     /**
      * Sets the carrier-to-noise density in dB-Hz.
+     * @hide
      */
+    @TestApi
     public void setCn0DbHz(double value) {
         mCn0DbHz = value;
     }
@@ -409,7 +432,9 @@
 
     /**
      * Sets the pseudorange rate at the timestamp in m/s.
+     * @hide
      */
+    @TestApi
     public void setPseudorangeRateMetersPerSecond(double value) {
         mPseudorangeRateMetersPerSecond = value;
     }
@@ -421,7 +446,16 @@
      *         value, {@code false} if it contains an uncorrected value.
      */
     public boolean isPseudorangeRateCorrected() {
-        return !isFlagSet(HAS_UNCORRECTED_PSEUDORANGE_RATE);
+        return mPseudorangeRateCorrected;
+    }
+
+    /**
+     * Sets whether the pseudorange corrected.
+     * @hide
+     */
+    @TestApi
+    public void setPseudorangeRateCorrected(boolean value) {
+        mPseudorangeRateCorrected = value;
     }
 
     /**
@@ -434,7 +468,9 @@
 
     /**
      * Sets the pseudorange's rate uncertainty (1-Sigma) in m/s.
+     * @hide
      */
+    @TestApi
     public void setPseudorangeRateUncertaintyMetersPerSecond(double value) {
         mPseudorangeRateUncertaintyMetersPerSecond = value;
     }
@@ -450,7 +486,9 @@
 
     /**
      * Sets the 'Accumulated Delta Range' state.
+     * @hide
      */
+    @TestApi
     public void setAccumulatedDeltaRangeState(int value) {
         mAccumulatedDeltaRangeState = value;
     }
@@ -500,7 +538,9 @@
 
     /**
      * Sets the accumulated delta range in meters.
+     * @hide
      */
+    @TestApi
     public void setAccumulatedDeltaRangeMeters(double value) {
         mAccumulatedDeltaRangeMeters = value;
     }
@@ -519,7 +559,10 @@
      * Sets the accumulated delta range's uncertainty (1-sigma) in meters.
      *
      * The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
+     *
+     * @hide
      */
+    @TestApi
     public void setAccumulatedDeltaRangeUncertaintyMeters(double value) {
         mAccumulatedDeltaRangeUncertaintyMeters = value;
     }
@@ -543,7 +586,9 @@
 
     /**
      * Sets the Carrier frequency (L1 or L2) in Hz.
+     * @hide
      */
+    @TestApi
     public void setCarrierFrequencyHz(float carrierFrequencyHz) {
         setFlag(HAS_CARRIER_FREQUENCY);
         mCarrierFrequencyHz = carrierFrequencyHz;
@@ -551,7 +596,9 @@
 
     /**
      * Resets the Carrier frequency (L1 or L2) in Hz.
+     * @hide
      */
+    @TestApi
     public void resetCarrierFrequencyHz() {
         resetFlag(HAS_CARRIER_FREQUENCY);
         mCarrierFrequencyHz = Float.NaN;
@@ -576,7 +623,9 @@
 
     /**
      * Sets the number of full carrier cycles between the satellite and the receiver.
+     * @hide
      */
+    @TestApi
     public void setCarrierCycles(long value) {
         setFlag(HAS_CARRIER_CYCLES);
         mCarrierCycles = value;
@@ -584,7 +633,9 @@
 
     /**
      * Resets the number of full carrier cycles between the satellite and the receiver.
+     * @hide
      */
+    @TestApi
     public void resetCarrierCycles() {
         resetFlag(HAS_CARRIER_CYCLES);
         mCarrierCycles = Long.MIN_VALUE;
@@ -613,7 +664,9 @@
 
     /**
      * Sets the RF phase detected by the receiver.
+     * @hide
      */
+    @TestApi
     public void setCarrierPhase(double value) {
         setFlag(HAS_CARRIER_PHASE);
         mCarrierPhase = value;
@@ -621,7 +674,9 @@
 
     /**
      * Resets the RF phase detected by the receiver.
+     * @hide
      */
+    @TestApi
     public void resetCarrierPhase() {
         resetFlag(HAS_CARRIER_PHASE);
         mCarrierPhase = Double.NaN;
@@ -646,7 +701,9 @@
 
     /**
      * Sets the Carrier-phase's uncertainty (1-Sigma) in cycles.
+     * @hide
      */
+    @TestApi
     public void setCarrierPhaseUncertainty(double value) {
         setFlag(HAS_CARRIER_PHASE_UNCERTAINTY);
         mCarrierPhaseUncertainty = value;
@@ -654,7 +711,9 @@
 
     /**
      * Resets the Carrier-phase's uncertainty (1-Sigma) in cycles.
+     * @hide
      */
+    @TestApi
     public void resetCarrierPhaseUncertainty() {
         resetFlag(HAS_CARRIER_PHASE_UNCERTAINTY);
         mCarrierPhaseUncertainty = Double.NaN;
@@ -670,7 +729,9 @@
 
     /**
      * Sets the 'multi-path' indicator.
+     * @hide
      */
+    @TestApi
     public void setMultipathIndicator(@MultipathIndicator int value) {
         mMultipathIndicator = value;
     }
@@ -710,7 +771,9 @@
 
     /**
      * Sets the Signal-to-noise ratio (SNR) in dB.
+     * @hide
      */
+    @TestApi
     public void setSnrInDb(double snrInDb) {
         setFlag(HAS_SNR);
         mSnrInDb = snrInDb;
@@ -718,7 +781,9 @@
 
     /**
      * Resets the Signal-to-noise ratio (SNR) in dB.
+     * @hide
      */
+    @TestApi
     public void resetSnrInDb() {
         resetFlag(HAS_SNR);
         mSnrInDb = Double.NaN;
@@ -748,6 +813,7 @@
             gnssMeasurement.mCarrierPhaseUncertainty = parcel.readDouble();
             gnssMeasurement.mMultipathIndicator = parcel.readInt();
             gnssMeasurement.mSnrInDb = parcel.readDouble();
+            gnssMeasurement.mPseudorangeRateCorrected = (parcel.readByte() != 0);
 
             return gnssMeasurement;
         }
@@ -779,6 +845,7 @@
         parcel.writeDouble(mCarrierPhaseUncertainty);
         parcel.writeInt(mMultipathIndicator);
         parcel.writeDouble(mSnrInDb);
+        parcel.writeByte((byte) (mPseudorangeRateCorrected ? 1 : 0));
     }
 
     @Override
@@ -876,6 +943,7 @@
         resetCarrierPhaseUncertainty();
         setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN);
         resetSnrInDb();
+        setPseudorangeRateCorrected(false);
     }
 
     private void setFlag(int flag) {
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index c0608e0..ac255c8 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -16,6 +16,7 @@
 
 package android.location;
 
+import android.annotation.TestApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.os.Parcel;
@@ -86,13 +87,19 @@
     private byte[] mData;
     private int mStatus;
 
-    GnssNavigationMessage() {
+    /**
+     * @hide
+     */
+    @TestApi
+    public GnssNavigationMessage() {
         initialize();
     }
 
     /**
      * Sets all contents to the values stored in the provided object.
+     * @hide
      */
+    @TestApi
     public void set(GnssNavigationMessage navigationMessage) {
         mType = navigationMessage.mType;
         mSvid = navigationMessage.mSvid;
@@ -104,7 +111,9 @@
 
     /**
      * Resets all the contents to its original state.
+     * @hide
      */
+    @TestApi
     public void reset() {
         initialize();
     }
@@ -119,7 +128,9 @@
 
     /**
      * Sets the type of the navigation message.
+     * @hide
      */
+    @TestApi
     public void setType(@GnssNavigationMessageType int value) {
         mType = value;
     }
@@ -165,7 +176,9 @@
 
     /**
      * Sets the Pseud-random number.
+     * @hide
      */
+    @TestApi
     public void setSvid(int value) {
         mSvid = value;
     }
@@ -182,7 +195,9 @@
 
     /**
      * Sets the Message Identifier.
+     * @hide
      */
+    @TestApi
     public void setMessageId(int value) {
         mMessageId = value;
     }
@@ -199,7 +214,9 @@
 
     /**
      * Sets the Sub-message identifier.
+     * @hide
      */
+    @TestApi
     public void setSubmessageId(int value) {
         mSubmessageId = value;
     }
@@ -215,7 +232,9 @@
 
     /**
      * Sets the data associated with the Navigation Message.
+     * @hide
      */
+    @TestApi
     public void setData(byte[] value) {
         if (value == null) {
             throw new InvalidParameterException("Data must be a non-null array");
@@ -233,7 +252,9 @@
 
     /**
      * Sets the status of the navigation message.
+     * @hide
      */
+    @TestApi
     public void setStatus(int value) {
         mStatus = value;
     }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 69d4487..d179171 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -21,6 +21,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothDevice;
 import android.content.ComponentName;
@@ -1004,6 +1005,9 @@
      * according to user settings.
      * <p>This method has no effect if the device implements a fixed volume policy
      * as indicated by {@link #isVolumeFixed()}.
+     * * <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed
+     * unless the app has been granted Do Not Disturb Access.
+     * See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
      * @param ringerMode The ringer mode, one of {@link #RINGER_MODE_NORMAL},
      *            {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}.
      * @see #getRingerMode()
@@ -1025,6 +1029,9 @@
      * Sets the volume index for a particular stream.
      * <p>This method has no effect if the device implements a fixed volume policy
      * as indicated by {@link #isVolumeFixed()}.
+     * <p>From N onward, volume adjustments that would toggle Do Not Disturb are not allowed unless
+     * the app has been granted Do Not Disturb Access.
+     * See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
      * @param streamType The stream whose volume index should be set.
      * @param index The volume index to set. See
      *            {@link #getStreamMaxVolume(int)} for the largest valid value.
@@ -1069,6 +1076,9 @@
      * <p>
      * This method has no effect if the device implements a fixed volume policy
      * as indicated by {@link #isVolumeFixed()}.
+     * <p>From N onward, stream mute changes that would toggle Do Not Disturb are not allowed unless
+     * the app has been granted Do Not Disturb Access.
+     * See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
      * <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.
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index d058ff3..ca306cc 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -394,30 +394,48 @@
      * value here as no error checking is or can be done.
      */
     /*package*/ AudioRecord(long nativeRecordInJavaObj) {
-        int[] session = { 0 };
-        int[] rates = { 0 };
-        //TODO: update native initialization when information about hardware init failure
-        //      due to capture device already open is available.
-        // Note that for this native_setup, we are providing an already created/initialized
-        // *Native* AudioRecord, so the attributes parameters to native_setup() are ignored.
-        int initResult = native_setup(new WeakReference<AudioRecord>(this),
-                null /*mAudioAttributes*/,
-                rates /*mSampleRates*/,
-                0 /*mChannelMask*/,
-                0 /*mChannelIndexMask*/,
-                0 /*mAudioFormat*/,
-                0 /*mNativeBufferSizeInBytes*/,
-                session,
-                ActivityThread.currentOpPackageName(),
-                nativeRecordInJavaObj);
-        if (initResult != SUCCESS) {
-            loge("Error code "+initResult+" when initializing native AudioRecord object.");
-            return; // with mState == STATE_UNINITIALIZED
+        mNativeRecorderInJavaObj = 0;
+        mNativeCallbackCookie = 0;
+        mNativeDeviceCallback = 0;
+
+        // other initialization...
+        if (nativeRecordInJavaObj != 0) {
+            deferred_connect(nativeRecordInJavaObj);
+        } else {
+            mState = STATE_UNINITIALIZED;
         }
+    }
 
-        mSessionId = session[0];
+    /**
+     * @hide
+     */
+    /* package */ void deferred_connect(long  nativeRecordInJavaObj) {
+        if (mState != STATE_INITIALIZED) {
+            int[] session = { 0 };
+            int[] rates = { 0 };
+            //TODO: update native initialization when information about hardware init failure
+            //      due to capture device already open is available.
+            // Note that for this native_setup, we are providing an already created/initialized
+            // *Native* AudioRecord, so the attributes parameters to native_setup() are ignored.
+            int initResult = native_setup(new WeakReference<AudioRecord>(this),
+                    null /*mAudioAttributes*/,
+                    rates /*mSampleRates*/,
+                    0 /*mChannelMask*/,
+                    0 /*mChannelIndexMask*/,
+                    0 /*mAudioFormat*/,
+                    0 /*mNativeBufferSizeInBytes*/,
+                    session,
+                    ActivityThread.currentOpPackageName(),
+                    nativeRecordInJavaObj);
+            if (initResult != SUCCESS) {
+                loge("Error code "+initResult+" when initializing native AudioRecord object.");
+                return; // with mState == STATE_UNINITIALIZED
+            }
 
-        mState = STATE_INITIALIZED;
+            mSessionId = session[0];
+
+            mState = STATE_INITIALIZED;
+        }
     }
 
     /**
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index bfbd3a5..e1dab09 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -526,11 +526,18 @@
      * the AudioTrackRoutingProxy subclass.
      * @param nativeTrackInJavaObj a C/C++ pointer to a native AudioTrack
      * (associated with an OpenSL ES player).
+     * IMPORTANT: For "N", this method is ONLY called to setup a Java routing proxy,
+     * i.e. IAndroidConfiguration::AcquireJavaProxy(). If we call with a 0 in nativeTrackInJavaObj
+     * it means that the OpenSL player interface hasn't been realized, so there is no native
+     * Audiotrack to connect to. In this case wait to call deferred_connect() until the
+     * OpenSLES interface is realized.
      */
     /*package*/ AudioTrack(long nativeTrackInJavaObj) {
         // "final"s
         mAttributes = null;
         mAppOps = null;
+        mNativeTrackInJavaObj = 0;
+        mJniData = 0;
 
         // remember which looper is associated with the AudioTrack instantiation
         Looper looper;
@@ -540,28 +547,41 @@
         mInitializationLooper = looper;
 
         // other initialization...
-        // Note that for this native_setup, we are providing an already created/initialized
-        // *Native* AudioTrack, so the attributes parameters to native_setup() are ignored.
-        int[] session = { 0 };
-        int[] rates = { 0 };
-        int initResult = native_setup(new WeakReference<AudioTrack>(this),
-                null /*mAttributes - NA*/,
-                rates /*sampleRate - NA*/,
-                0 /*mChannelMask - NA*/,
-                0 /*mChannelIndexMask - NA*/,
-                0 /*mAudioFormat - NA*/,
-                0 /*mNativeBufferSizeInBytes - NA*/,
-                0 /*mDataLoadMode - NA*/,
-                session,
-                nativeTrackInJavaObj);
-        if (initResult != SUCCESS) {
-            loge("Error code "+initResult+" when initializing AudioTrack.");
-            return; // with mState == STATE_UNINITIALIZED
+        if (nativeTrackInJavaObj != 0) {
+            deferred_connect(nativeTrackInJavaObj);
+        } else {
+            mState = STATE_UNINITIALIZED;
         }
+    }
 
-        mSessionId = session[0];
+    /**
+     * @hide
+     */
+    /* package */ void deferred_connect(long nativeTrackInJavaObj) {
+        if (mState != STATE_INITIALIZED) {
+            // Note that for this native_setup, we are providing an already created/initialized
+            // *Native* AudioTrack, so the attributes parameters to native_setup() are ignored.
+            int[] session = { 0 };
+            int[] rates = { 0 };
+            int initResult = native_setup(new WeakReference<AudioTrack>(this),
+                    null /*mAttributes - NA*/,
+                    rates /*sampleRate - NA*/,
+                    0 /*mChannelMask - NA*/,
+                    0 /*mChannelIndexMask - NA*/,
+                    0 /*mAudioFormat - NA*/,
+                    0 /*mNativeBufferSizeInBytes - NA*/,
+                    0 /*mDataLoadMode - NA*/,
+                    session,
+                    nativeTrackInJavaObj);
+            if (initResult != SUCCESS) {
+                loge("Error code "+initResult+" when initializing AudioTrack.");
+                return; // with mState == STATE_UNINITIALIZED
+            }
 
-        mState = STATE_INITIALIZED;
+            mSessionId = session[0];
+
+            mState = STATE_INITIALIZED;
+        }
     }
 
     /**
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 3fa078f..1fc236a 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -24,7 +24,6 @@
 import android.system.Os;
 import android.system.OsConstants;
 import android.util.Log;
-import android.util.Pair;
 
 import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
@@ -47,6 +46,7 @@
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 import java.util.TimeZone;
 import java.util.regex.Pattern;
 
@@ -65,84 +65,267 @@
     private static final boolean DEBUG = false;
 
     // The Exif tag names
+    /** Type is String. */
+    public static final String TAG_ARTIST = "Artist";
     /** Type is int. */
-    public static final String TAG_ORIENTATION = "Orientation";
+    public static final String TAG_BITS_PER_SAMPLE = "BitsPerSample";
+    /** Type is int. */
+    public static final String TAG_COMPRESSION = "Compression";
+    /** Type is String. */
+    public static final String TAG_COPYRIGHT = "Copyright";
     /** Type is String. */
     public static final String TAG_DATETIME = "DateTime";
     /** Type is String. */
+    public static final String TAG_IMAGE_DESCRIPTION = "ImageDescription";
+    /** Type is int. */
+    public static final String TAG_IMAGE_LENGTH = "ImageLength";
+    /** Type is int. */
+    public static final String TAG_IMAGE_WIDTH = "ImageWidth";
+    /** Type is int. */
+    public static final String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
+    /** Type is int. */
+    public static final String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
+    /** Type is String. */
     public static final String TAG_MAKE = "Make";
     /** Type is String. */
     public static final String TAG_MODEL = "Model";
     /** Type is int. */
-    public static final String TAG_FLASH = "Flash";
+    public static final String TAG_ORIENTATION = "Orientation";
     /** Type is int. */
-    public static final String TAG_IMAGE_WIDTH = "ImageWidth";
+    public static final String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
     /** Type is int. */
-    public static final String TAG_IMAGE_LENGTH = "ImageLength";
-    /** String. Format is "num1/denom1,num2/denom2,num3/denom3". */
-    public static final String TAG_GPS_LATITUDE = "GPSLatitude";
-    /** String. Format is "num1/denom1,num2/denom2,num3/denom3". */
-    public static final String TAG_GPS_LONGITUDE = "GPSLongitude";
+    public static final String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
+    /** Type is rational. */
+    public static final String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
+    /** Type is rational. */
+    public static final String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
+    /** Type is int. */
+    public static final String TAG_RESOLUTION_UNIT = "ResolutionUnit";
+    /** Type is int. */
+    public static final String TAG_ROWS_PER_STRIP = "RowsPerStrip";
+    /** Type is int. */
+    public static final String TAG_SAMPLES_PER_PIXEL = "SamplesPerPixel";
     /** Type is String. */
-    public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
+    public static final String TAG_SOFTWARE = "Software";
+    /** Type is int. */
+    public static final String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
+    /** Type is int. */
+    public static final String TAG_STRIP_OFFSETS = "StripOffsets";
+    /** Type is int. */
+    public static final String TAG_TRANSFER_FUNCTION = "TransferFunction";
+    /** Type is rational. */
+    public static final String TAG_WHITE_POINT = "WhitePoint";
+    /** Type is rational. */
+    public static final String TAG_X_RESOLUTION = "XResolution";
+    /** Type is rational. */
+    public static final String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients";
+    /** Type is int. */
+    public static final String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
+    /** Type is int. */
+    public static final String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
+    /** Type is rational. */
+    public static final String TAG_Y_RESOLUTION = "YResolution";
+    /** Type is rational. */
+    public static final String TAG_APERTURE_VALUE = "ApertureValue";
+    /** Type is rational. */
+    public static final String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
     /** Type is String. */
-    public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    public static final String TAG_CFA_PATTERN = "CFAPattern";
+    /** Type is int. */
+    public static final String TAG_COLOR_SPACE = "ColorSpace";
     /** Type is String. */
+    public static final String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
+    /** Type is rational. */
+    public static final String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
+    /** Type is int. */
+    public static final String TAG_CONTRAST = "Contrast";
+    /** Type is int. */
+    public static final String TAG_CUSTOM_RENDERED = "CustomRendered";
+    /** Type is String. */
+    public static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    /** Type is String. */
+    public static final String TAG_DATETIME_ORIGINAL = "DateTimeOriginal";
+    /** Type is String. */
+    public static final String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription";
+    /** Type is double. */
+    public static final String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+    /** Type is String. */
+    public static final String TAG_EXIF_VERSION = "ExifVersion";
+    /** Type is double. */
+    public static final String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+    /** Type is rational. */
+    public static final String TAG_EXPOSURE_INDEX = "ExposureIndex";
+    /** Type is int. */
+    public static final String TAG_EXPOSURE_MODE = "ExposureMode";
+    /** Type is int. */
+    public static final String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
+    /** Type is double. */
     public static final String TAG_EXPOSURE_TIME = "ExposureTime";
     /** Type is String. */
+    public static final String TAG_F_NUMBER = "FNumber";
+    /** Type is String. */
     public static final String TAG_APERTURE = "FNumber";
     /** Type is String. */
+    public static final String TAG_FILE_SOURCE = "FileSource";
+    /** Type is int. */
+    public static final String TAG_FLASH = "Flash";
+    /** Type is rational. */
+    public static final String TAG_FLASH_ENERGY = "FlashEnergy";
+    /** Type is String. */
+    public static final String TAG_FLASHPIX_VERSION = "FlashpixVersion";
+    /** Type is rational. */
+    public static final String TAG_FOCAL_LENGTH = "FocalLength";
+    /** Type is int. */
+    public static final String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm";
+    /** Type is int. */
+    public static final String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit";
+    /** Type is rational. */
+    public static final String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution";
+    /** Type is rational. */
+    public static final String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
+    /** Type is rational. */
+    public static final String TAG_GAIN_CONTROL = "GainControl";
+    /** Type is String. */
+    public static final String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
+    /** Type is String. */
     public static final String TAG_ISO = "ISOSpeedRatings";
     /** Type is String. */
-    public static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    public static final String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
+    /** Type is int. */
+    public static final String TAG_LIGHT_SOURCE = "LightSource";
+    /** Type is String. */
+    public static final String TAG_MAKER_NOTE = "MakerNote";
+    /** Type is rational. */
+    public static final String TAG_MAX_APERTURE_VALUE = "MaxApertureValue";
+    /** Type is int. */
+    public static final String TAG_METERING_MODE = "MeteringMode";
+    /** Type is String. */
+    public static final String TAG_OECF = "OECF";
+    /** Type is int. */
+    public static final String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
+    /** Type is int. */
+    public static final String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
+    /** Type is String. */
+    public static final String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
+    /** Type is int. */
+    public static final String TAG_SATURATION = "Saturation";
+    /** Type is int. */
+    public static final String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
+    /** Type is String. */
+    public static final String TAG_SCENE_TYPE = "SceneType";
+    /** Type is int. */
+    public static final String TAG_SENSING_METHOD = "SensingMethod";
+    /** Type is int. */
+    public static final String TAG_SHARPNESS = "Sharpness";
+    /** Type is rational. */
+    public static final String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
+    /** Type is String. */
+    public static final String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
+    /** Type is String. */
+    public static final String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
     /** Type is int. */
     public static final String TAG_SUBSEC_TIME = "SubSecTime";
+    /** Type is int. @hide */
+    public static final String TAG_SUBSECTIME = "SubSecTime";
+    /** Type is int. */
+    public static final String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized";
+    /** Type is int. */
+    public static final String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
     /** Type is int. */
     public static final String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
     /** Type is int. */
-    public static final String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
-
-    /**
-     * @hide
-     */
-    public static final String TAG_SUBSECTIME = "SubSecTime";
-
+    public static final String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
+    /** Type is int. */
+    public static final String TAG_SUBJECT_AREA = "SubjectArea";
+    /** Type is double. */
+    public static final String TAG_SUBJECT_DISTANCE = "SubjectDistance";
+    /** Type is int. */
+    public static final String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange";
+    /** Type is int. */
+    public static final String TAG_SUBJECT_LOCATION = "SubjectLocation";
+    /** Type is String. */
+    public static final String TAG_USER_COMMENT = "UserComment";
+    /** Type is int. */
+    public static final String TAG_WHITE_BALANCE = "WhiteBalance";
     /**
      * The altitude (in meters) based on the reference in TAG_GPS_ALTITUDE_REF.
      * Type is rational.
      */
     public static final String TAG_GPS_ALTITUDE = "GPSAltitude";
-
     /**
      * 0 if the altitude is above sea level. 1 if the altitude is below sea
      * level. Type is int.
      */
     public static final String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
-
     /** Type is String. */
-    public static final String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+    public static final String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
+    /** Type is rational. */
+    public static final String TAG_GPS_DOP = "GPSDOP";
     /** Type is String. */
     public static final String TAG_GPS_DATESTAMP = "GPSDateStamp";
-    /** Type is int. */
-    public static final String TAG_WHITE_BALANCE = "WhiteBalance";
     /** Type is rational. */
-    public static final String TAG_FOCAL_LENGTH = "FocalLength";
+    public static final String TAG_GPS_DEST_BEARING = "GPSDestBearing";
+    /** Type is String. */
+    public static final String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef";
+    /** Type is rational. */
+    public static final String TAG_GPS_DEST_DISTANCE = "GPSDestDistance";
+    /** Type is String. */
+    public static final String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef";
+    /** Type is rational. */
+    public static final String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude";
+    /** Type is String. */
+    public static final String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef";
+    /** Type is rational. */
+    public static final String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude";
+    /** Type is String. */
+    public static final String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
+    /** Type is int. */
+    public static final String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
+    /** Type is rational. */
+    public static final String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
+    /** Type is String. */
+    public static final String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
+    /** String. Format is "num1/denom1,num2/denom2,num3/denom3". */
+    public static final String TAG_GPS_LATITUDE = "GPSLatitude";
+    /** Type is String. */
+    public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
+    /** String. Format is "num1/denom1,num2/denom2,num3/denom3". */
+    public static final String TAG_GPS_LONGITUDE = "GPSLongitude";
+    /** Type is String. */
+    public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    /** Type is String. */
+    public static final String TAG_GPS_MAP_DATUM = "GPSMapDatum";
+    /** Type is String. */
+    public static final String TAG_GPS_MEASURE_MODE = "GPSMeasureMode";
     /** Type is String. Name of GPS processing method used for location finding. */
     public static final String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
-    /** Type is double. */
-    public static final String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
-    /** Type is double. */
-    public static final String TAG_SUBJECT_DISTANCE = "SubjectDistance";
-    /** Type is double. */
-    public static final String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+    /** Type is String. */
+    public static final String TAG_GPS_SATELLITES = "GPSSatellites";
+    /** Type is rational. */
+    public static final String TAG_GPS_SPEED = "GPSSpeed";
+    /** Type is String. */
+    public static final String TAG_GPS_SPEED_REF = "GPSSpeedRef";
+    /** Type is String. */
+    public static final String TAG_GPS_STATUS = "GPSStatus";
+    /** Type is String. */
+    public static final String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
+    /** Type is rational. */
+    public static final String TAG_GPS_TRACK = "GPSTrack";
+    /** Type is String. */
+    public static final String TAG_GPS_TRACK_REF = "GPSTrackRef";
+    /** Type is String. */
+    public static final String TAG_GPS_VERSION_ID = "GPSVersionID";
+    /** Type is String. */
+    public static final String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
     /** Type is int. */
-    public static final String TAG_LIGHT_SOURCE = "LightSource";
+    public static final String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
     /** Type is int. */
-    public static final String TAG_METERING_MODE = "MeteringMode";
-    /** Type is int. */
-    public static final String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
-    /** Type is int. */
-    public static final String TAG_EXPOSURE_MODE = "ExposureMode";
+    public static final String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
+
+    // Private tags used for pointing the other IFD offset. The types of the following tags are int.
+    private static final String TAG_EXIF_IFD_POINTER = "ExifIFDPointer";
+    private static final String TAG_GPS_INFO_IFD_POINTER = "GPSInfoIFDPointer";
+    private static final String TAG_INTEROPERABILITY_IFD_POINTER = "InteroperabilityIFDPointer";
 
     // Private tags used for thumbnail information.
     private static final String TAG_HAS_THUMBNAIL = "hasThumbnail";
@@ -215,171 +398,171 @@
 
     // Primary image IFD TIFF tags (See JEITA CP-3451 Table 14. page 54).
     private static final ExifTag[] IFD_TIFF_TAGS = new ExifTag[] {
-            new ExifTag("ImageWidth", 256),
-            new ExifTag("ImageLength", 257),
-            new ExifTag("BitsPerSample", 258),
-            new ExifTag("Compression", 259),
-            new ExifTag("PhotometricInterpretation", 262),
-            new ExifTag("ImageDescription", 270),
-            new ExifTag("Make", 271),
-            new ExifTag("Model", 272),
-            new ExifTag("StripOffsets", 273),
-            new ExifTag("Orientation", 274),
-            new ExifTag("SamplesPerPixel", 277),
-            new ExifTag("RowsPerStrip", 278),
-            new ExifTag("StripByteCounts", 279),
-            new ExifTag("XResolution", 282),
-            new ExifTag("YResolution", 283),
-            new ExifTag("PlanarConfiguration", 284),
-            new ExifTag("ResolutionUnit", 296),
-            new ExifTag("TransferFunction", 301),
-            new ExifTag("Software", 305),
-            new ExifTag("DateTime", 306),
-            new ExifTag("Artist", 315),
-            new ExifTag("WhitePoint", 318),
-            new ExifTag("PrimaryChromaticities", 319),
-            new ExifTag("JPEGInterchangeFormat", 513),
-            new ExifTag("JPEGInterchangeFormatLength", 514),
-            new ExifTag("YCbCrCoefficients", 529),
-            new ExifTag("YCbCrSubSampling", 530),
-            new ExifTag("YCbCrPositioning", 531),
-            new ExifTag("ReferenceBlackWhite", 532),
-            new ExifTag("Copyright", 33432),
-            new ExifTag("ExifIFDPointer", 34665),
-            new ExifTag("GPSInfoIFDPointer", 34853),
+            new ExifTag(TAG_IMAGE_WIDTH, 256),
+            new ExifTag(TAG_IMAGE_LENGTH, 257),
+            new ExifTag(TAG_BITS_PER_SAMPLE, 258),
+            new ExifTag(TAG_COMPRESSION, 259),
+            new ExifTag(TAG_PHOTOMETRIC_INTERPRETATION, 262),
+            new ExifTag(TAG_IMAGE_DESCRIPTION, 270),
+            new ExifTag(TAG_MAKE, 271),
+            new ExifTag(TAG_MODEL, 272),
+            new ExifTag(TAG_STRIP_OFFSETS, 273),
+            new ExifTag(TAG_ORIENTATION, 274),
+            new ExifTag(TAG_SAMPLES_PER_PIXEL, 277),
+            new ExifTag(TAG_ROWS_PER_STRIP, 278),
+            new ExifTag(TAG_STRIP_BYTE_COUNTS, 279),
+            new ExifTag(TAG_X_RESOLUTION, 282),
+            new ExifTag(TAG_Y_RESOLUTION, 283),
+            new ExifTag(TAG_PLANAR_CONFIGURATION, 284),
+            new ExifTag(TAG_RESOLUTION_UNIT, 296),
+            new ExifTag(TAG_TRANSFER_FUNCTION, 301),
+            new ExifTag(TAG_SOFTWARE, 305),
+            new ExifTag(TAG_DATETIME, 306),
+            new ExifTag(TAG_ARTIST, 315),
+            new ExifTag(TAG_WHITE_POINT, 318),
+            new ExifTag(TAG_PRIMARY_CHROMATICITIES, 319),
+            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513),
+            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 514),
+            new ExifTag(TAG_Y_CB_CR_COEFFICIENTS, 529),
+            new ExifTag(TAG_Y_CB_CR_SUB_SAMPLING, 530),
+            new ExifTag(TAG_Y_CB_CR_POSITIONING, 531),
+            new ExifTag(TAG_REFERENCE_BLACK_WHITE, 532),
+            new ExifTag(TAG_COPYRIGHT, 33432),
+            new ExifTag(TAG_EXIF_IFD_POINTER, 34665),
+            new ExifTag(TAG_GPS_INFO_IFD_POINTER, 34853),
     };
     // Primary image IFD Exif Private tags (See JEITA CP-3451 Table 15. page 55).
     private static final ExifTag[] IFD_EXIF_TAGS = new ExifTag[] {
-            new ExifTag("ExposureTime", 33434),
-            new ExifTag("FNumber", 33437),
-            new ExifTag("ExposureProgram", 34850),
-            new ExifTag("SpectralSensitivity", 34852),
-            new ExifTag("ISOSpeedRatings", 34855),
-            new ExifTag("OECF", 34856),
-            new ExifTag("ExifVersion", 36864),
-            new ExifTag("DateTimeOriginal", 36867),
-            new ExifTag("DateTimeDigitized", 36868),
-            new ExifTag("ComponentsConfiguration", 37121),
-            new ExifTag("CompressedBitsPerPixel", 37122),
-            new ExifTag("ShutterSpeedValue", 37377),
-            new ExifTag("ApertureValue", 37378),
-            new ExifTag("BrightnessValue", 37379),
-            new ExifTag("ExposureBiasValue", 37380),
-            new ExifTag("MaxApertureValue", 37381),
-            new ExifTag("SubjectDistance", 37382),
-            new ExifTag("MeteringMode", 37383),
-            new ExifTag("LightSource", 37384),
-            new ExifTag("Flash", 37385),
-            new ExifTag("FocalLength", 37386),
-            new ExifTag("SubjectArea", 37396),
-            new ExifTag("MakerNote", 37500),
-            new ExifTag("UserComment", 37510),
-            new ExifTag("SubSecTime", 37520),
-            new ExifTag("SubSecTimeOriginal", 37521),
-            new ExifTag("SubSecTimeDigitized", 37522),
-            new ExifTag("FlashpixVersion", 40960),
-            new ExifTag("ColorSpace", 40961),
-            new ExifTag("PixelXDimension", 40962),
-            new ExifTag("PixelYDimension", 40963),
-            new ExifTag("RelatedSoundFile", 40964),
-            new ExifTag("InteroperabilityIFDPointer", 40965),
-            new ExifTag("FlashEnergy", 41483),
-            new ExifTag("SpatialFrequencyResponse", 41484),
-            new ExifTag("FocalPlaneXResolution", 41486),
-            new ExifTag("FocalPlaneYResolution", 41487),
-            new ExifTag("FocalPlaneResolutionUnit", 41488),
-            new ExifTag("SubjectLocation", 41492),
-            new ExifTag("ExposureIndex", 41493),
-            new ExifTag("SensingMethod", 41495),
-            new ExifTag("FileSource", 41728),
-            new ExifTag("SceneType", 41729),
-            new ExifTag("CFAPattern", 41730),
-            new ExifTag("CustomRendered", 41985),
-            new ExifTag("ExposureMode", 41986),
-            new ExifTag("WhiteBalance", 41987),
-            new ExifTag("DigitalZoomRatio", 41988),
-            new ExifTag("FocalLengthIn35mmFilm", 41989),
-            new ExifTag("SceneCaptureType", 41990),
-            new ExifTag("GainControl", 41991),
-            new ExifTag("Contrast", 41992),
-            new ExifTag("Saturation", 41993),
-            new ExifTag("Sharpness", 41994),
-            new ExifTag("DeviceSettingDescription", 41995),
-            new ExifTag("SubjectDistanceRange", 41996),
-            new ExifTag("ImageUniqueID", 42016),
+            new ExifTag(TAG_EXPOSURE_TIME, 33434),
+            new ExifTag(TAG_F_NUMBER, 33437),
+            new ExifTag(TAG_EXPOSURE_PROGRAM, 34850),
+            new ExifTag(TAG_SPECTRAL_SENSITIVITY, 34852),
+            new ExifTag(TAG_ISO, 34855),
+            new ExifTag(TAG_OECF, 34856),
+            new ExifTag(TAG_EXIF_VERSION, 36864),
+            new ExifTag(TAG_DATETIME_ORIGINAL, 36867),
+            new ExifTag(TAG_DATETIME_DIGITIZED, 36868),
+            new ExifTag(TAG_COMPONENTS_CONFIGURATION, 37121),
+            new ExifTag(TAG_COMPRESSED_BITS_PER_PIXEL, 37122),
+            new ExifTag(TAG_SHUTTER_SPEED_VALUE, 37377),
+            new ExifTag(TAG_APERTURE_VALUE, 37378),
+            new ExifTag(TAG_BRIGHTNESS_VALUE, 37379),
+            new ExifTag(TAG_EXPOSURE_BIAS_VALUE, 37380),
+            new ExifTag(TAG_MAX_APERTURE_VALUE, 37381),
+            new ExifTag(TAG_SUBJECT_DISTANCE, 37382),
+            new ExifTag(TAG_METERING_MODE, 37383),
+            new ExifTag(TAG_LIGHT_SOURCE, 37384),
+            new ExifTag(TAG_FLASH, 37385),
+            new ExifTag(TAG_FOCAL_LENGTH, 37386),
+            new ExifTag(TAG_SUBJECT_AREA, 37396),
+            new ExifTag(TAG_MAKER_NOTE, 37500),
+            new ExifTag(TAG_USER_COMMENT, 37510),
+            new ExifTag(TAG_SUBSEC_TIME, 37520),
+            new ExifTag(TAG_SUBSEC_TIME_ORIG, 37521),
+            new ExifTag(TAG_SUBSEC_TIME_DIG, 37522),
+            new ExifTag(TAG_FLASHPIX_VERSION, 40960),
+            new ExifTag(TAG_COLOR_SPACE, 40961),
+            new ExifTag(TAG_PIXEL_X_DIMENSION, 40962),
+            new ExifTag(TAG_PIXEL_Y_DIMENSION, 40963),
+            new ExifTag(TAG_RELATED_SOUND_FILE, 40964),
+            new ExifTag(TAG_INTEROPERABILITY_IFD_POINTER, 40965),
+            new ExifTag(TAG_FLASH_ENERGY, 41483),
+            new ExifTag(TAG_SPATIAL_FREQUENCY_RESPONSE, 41484),
+            new ExifTag(TAG_FOCAL_PLANE_X_RESOLUTION, 41486),
+            new ExifTag(TAG_FOCAL_PLANE_Y_RESOLUTION, 41487),
+            new ExifTag(TAG_FOCAL_PLANE_RESOLUTION_UNIT, 41488),
+            new ExifTag(TAG_SUBJECT_LOCATION, 41492),
+            new ExifTag(TAG_EXPOSURE_INDEX, 41493),
+            new ExifTag(TAG_SENSING_METHOD, 41495),
+            new ExifTag(TAG_FILE_SOURCE, 41728),
+            new ExifTag(TAG_SCENE_TYPE, 41729),
+            new ExifTag(TAG_CFA_PATTERN, 41730),
+            new ExifTag(TAG_CUSTOM_RENDERED, 41985),
+            new ExifTag(TAG_EXPOSURE_MODE, 41986),
+            new ExifTag(TAG_WHITE_BALANCE, 41987),
+            new ExifTag(TAG_DIGITAL_ZOOM_RATIO, 41988),
+            new ExifTag(TAG_FOCAL_LENGTH_IN_35MM_FILM, 41989),
+            new ExifTag(TAG_SCENE_CAPTURE_TYPE, 41990),
+            new ExifTag(TAG_GAIN_CONTROL, 41991),
+            new ExifTag(TAG_CONTRAST, 41992),
+            new ExifTag(TAG_SATURATION, 41993),
+            new ExifTag(TAG_SHARPNESS, 41994),
+            new ExifTag(TAG_DEVICE_SETTING_DESCRIPTION, 41995),
+            new ExifTag(TAG_SUBJECT_DISTANCE_RANGE, 41996),
+            new ExifTag(TAG_IMAGE_UNIQUE_ID, 42016),
     };
     // Primary image IFD GPS Info tags (See JEITA CP-3451 Table 16. page 56).
     private static final ExifTag[] IFD_GPS_TAGS = new ExifTag[] {
-            new ExifTag("GPSVersionID", 0),
-            new ExifTag("GPSLatitudeRef", 1),
-            new ExifTag("GPSLatitude", 2),
-            new ExifTag("GPSLongitudeRef", 3),
-            new ExifTag("GPSLongitude", 4),
-            new ExifTag("GPSAltitudeRef", 5),
-            new ExifTag("GPSAltitude", 6),
-            new ExifTag("GPSTimeStamp", 7),
-            new ExifTag("GPSSatellites", 8),
-            new ExifTag("GPSStatus", 9),
-            new ExifTag("GPSMeasureMode", 10),
-            new ExifTag("GPSDOP", 11),
-            new ExifTag("GPSSpeedRef", 12),
-            new ExifTag("GPSSpeed", 13),
-            new ExifTag("GPSTrackRef", 14),
-            new ExifTag("GPSTrack", 15),
-            new ExifTag("GPSImgDirectionRef", 16),
-            new ExifTag("GPSImgDirection", 17),
-            new ExifTag("GPSMapDatum", 18),
-            new ExifTag("GPSDestLatitudeRef", 19),
-            new ExifTag("GPSDestLatitude", 20),
-            new ExifTag("GPSDestLongitudeRef", 21),
-            new ExifTag("GPSDestLongitude", 22),
-            new ExifTag("GPSDestBearingRef", 23),
-            new ExifTag("GPSDestBearing", 24),
-            new ExifTag("GPSDestDistanceRef", 25),
-            new ExifTag("GPSDestDistance", 26),
-            new ExifTag("GPSProcessingMethod", 27),
-            new ExifTag("GPSAreaInformation", 28),
-            new ExifTag("GPSDateStamp", 29),
-            new ExifTag("GPSDifferential", 30),
+            new ExifTag(TAG_GPS_VERSION_ID, 0),
+            new ExifTag(TAG_GPS_LATITUDE_REF, 1),
+            new ExifTag(TAG_GPS_LATITUDE, 2),
+            new ExifTag(TAG_GPS_LONGITUDE_REF, 3),
+            new ExifTag(TAG_GPS_LONGITUDE, 4),
+            new ExifTag(TAG_GPS_ALTITUDE_REF, 5),
+            new ExifTag(TAG_GPS_ALTITUDE, 6),
+            new ExifTag(TAG_GPS_TIMESTAMP, 7),
+            new ExifTag(TAG_GPS_SATELLITES, 8),
+            new ExifTag(TAG_GPS_STATUS, 9),
+            new ExifTag(TAG_GPS_MEASURE_MODE, 10),
+            new ExifTag(TAG_GPS_DOP, 11),
+            new ExifTag(TAG_GPS_SPEED_REF, 12),
+            new ExifTag(TAG_GPS_SPEED, 13),
+            new ExifTag(TAG_GPS_TRACK_REF, 14),
+            new ExifTag(TAG_GPS_TRACK, 15),
+            new ExifTag(TAG_GPS_IMG_DIRECTION_REF, 16),
+            new ExifTag(TAG_GPS_IMG_DIRECTION, 17),
+            new ExifTag(TAG_GPS_MAP_DATUM, 18),
+            new ExifTag(TAG_GPS_DEST_LATITUDE_REF, 19),
+            new ExifTag(TAG_GPS_DEST_LATITUDE, 20),
+            new ExifTag(TAG_GPS_DEST_LONGITUDE_REF, 21),
+            new ExifTag(TAG_GPS_DEST_LONGITUDE, 22),
+            new ExifTag(TAG_GPS_DEST_BEARING_REF, 23),
+            new ExifTag(TAG_GPS_DEST_BEARING, 24),
+            new ExifTag(TAG_GPS_DEST_DISTANCE_REF, 25),
+            new ExifTag(TAG_GPS_DEST_DISTANCE, 26),
+            new ExifTag(TAG_GPS_PROCESSING_METHOD, 27),
+            new ExifTag(TAG_GPS_AREA_INFORMATION, 28),
+            new ExifTag(TAG_GPS_DATESTAMP, 29),
+            new ExifTag(TAG_GPS_DIFFERENTIAL, 30),
     };
     // Primary image IFD Interoperability tag (See JEITA CP-3451 Table 17. page 56).
     private static final ExifTag[] IFD_INTEROPERABILITY_TAGS = new ExifTag[] {
-            new ExifTag("InteroperabilityIndex", 1),
+            new ExifTag(TAG_INTEROPERABILITY_INDEX, 1),
     };
     // IFD Thumbnail tags (See JEITA CP-3451 Table 18. page 57).
     private static final ExifTag[] IFD_THUMBNAIL_TAGS = new ExifTag[] {
-            new ExifTag("ThumbnailImageWidth", 256),
-            new ExifTag("ThumbnailImageLength", 257),
-            new ExifTag("BitsPerSample", 258),
-            new ExifTag("Compression", 259),
-            new ExifTag("PhotometricInterpretation", 262),
-            new ExifTag("ImageDescription", 270),
-            new ExifTag("Make", 271),
-            new ExifTag("Model", 272),
-            new ExifTag("StripOffsets", 273),
-            new ExifTag("Orientation", 274),
-            new ExifTag("SamplesPerPixel", 277),
-            new ExifTag("RowsPerStrip", 278),
-            new ExifTag("StripByteCounts", 279),
-            new ExifTag("XResolution", 282),
-            new ExifTag("YResolution", 283),
-            new ExifTag("PlanarConfiguration", 284),
-            new ExifTag("ResolutionUnit", 296),
-            new ExifTag("TransferFunction", 301),
-            new ExifTag("Software", 305),
-            new ExifTag("DateTime", 306),
-            new ExifTag("Artist", 315),
-            new ExifTag("WhitePoint", 318),
-            new ExifTag("PrimaryChromaticities", 319),
-            new ExifTag("JPEGInterchangeFormat", 513),
-            new ExifTag("JPEGInterchangeFormatLength", 514),
-            new ExifTag("YCbCrCoefficients", 529),
-            new ExifTag("YCbCrSubSampling", 530),
-            new ExifTag("YCbCrPositioning", 531),
-            new ExifTag("ReferenceBlackWhite", 532),
-            new ExifTag("Copyright", 33432),
-            new ExifTag("ExifIFDPointer", 34665),
-            new ExifTag("GPSInfoIFDPointer", 34853),
+            new ExifTag(TAG_THUMBNAIL_IMAGE_WIDTH, 256),
+            new ExifTag(TAG_THUMBNAIL_IMAGE_LENGTH, 257),
+            new ExifTag(TAG_BITS_PER_SAMPLE, 258),
+            new ExifTag(TAG_COMPRESSION, 259),
+            new ExifTag(TAG_PHOTOMETRIC_INTERPRETATION, 262),
+            new ExifTag(TAG_IMAGE_DESCRIPTION, 270),
+            new ExifTag(TAG_MAKE, 271),
+            new ExifTag(TAG_MODEL, 272),
+            new ExifTag(TAG_STRIP_OFFSETS, 273),
+            new ExifTag(TAG_ORIENTATION, 274),
+            new ExifTag(TAG_SAMPLES_PER_PIXEL, 277),
+            new ExifTag(TAG_ROWS_PER_STRIP, 278),
+            new ExifTag(TAG_STRIP_BYTE_COUNTS, 279),
+            new ExifTag(TAG_X_RESOLUTION, 282),
+            new ExifTag(TAG_Y_RESOLUTION, 283),
+            new ExifTag(TAG_PLANAR_CONFIGURATION, 284),
+            new ExifTag(TAG_RESOLUTION_UNIT, 296),
+            new ExifTag(TAG_TRANSFER_FUNCTION, 301),
+            new ExifTag(TAG_SOFTWARE, 305),
+            new ExifTag(TAG_DATETIME, 306),
+            new ExifTag(TAG_ARTIST, 315),
+            new ExifTag(TAG_WHITE_POINT, 318),
+            new ExifTag(TAG_PRIMARY_CHROMATICITIES, 319),
+            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513),
+            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 514),
+            new ExifTag(TAG_Y_CB_CR_COEFFICIENTS, 529),
+            new ExifTag(TAG_Y_CB_CR_SUB_SAMPLING, 530),
+            new ExifTag(TAG_Y_CB_CR_POSITIONING, 531),
+            new ExifTag(TAG_REFERENCE_BLACK_WHITE, 532),
+            new ExifTag(TAG_COPYRIGHT, 33432),
+            new ExifTag(TAG_EXIF_IFD_POINTER, 34665),
+            new ExifTag(TAG_GPS_INFO_IFD_POINTER, 34853),
     };
 
     // See JEITA CP-3451 Figure 5. page 9.
@@ -398,9 +581,9 @@
     };
     // List of tags for pointing to the other image file directory offset.
     private static final ExifTag[] IFD_POINTER_TAGS = new ExifTag[] {
-            new ExifTag("ExifIFDPointer", 34665),
-            new ExifTag("GPSInfoPointer", 34853),
-            new ExifTag("InteroperabilityIFDPointer", 40965),
+            new ExifTag(TAG_EXIF_IFD_POINTER, 34665),
+            new ExifTag(TAG_GPS_INFO_IFD_POINTER, 34853),
+            new ExifTag(TAG_INTEROPERABILITY_IFD_POINTER, 40965),
     };
     // List of indices of the indicated tag groups according to the IFD_POINTER_TAGS
     private static final int[] IFD_POINTER_TAG_HINTS = new int[] {
@@ -408,15 +591,14 @@
     };
     // Tags for indicating the thumbnail offset and length
     private static final ExifTag JPEG_INTERCHANGE_FORMAT_TAG =
-            new ExifTag("JPEGInterchangeFormat", 513);
+            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513);
     private static final ExifTag JPEG_INTERCHANGE_FORMAT_LENGTH_TAG =
-            new ExifTag("JPEGInterchangeFormatLength", 514);
+            new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 514);
 
     // Mappings from tag number to tag name and each item represents one IFD tag group.
     private static final HashMap[] sExifTagMapsForReading = new HashMap[EXIF_TAGS.length];
-    // Mapping from tag name to tag number and the corresponding tag group.
-    private static final HashMap<String, Pair<Integer, Integer>> sExifTagMapForWriting =
-            new HashMap<>();
+    // Mappings from tag name to tag number and each item represents one IFD tag group.
+    private static final HashMap[] sExifTagMapsForWriting = new HashMap[EXIF_TAGS.length];
 
     // See JPEG File Interchange Format Version 1.02.
     // The following values are defined for handling JPEG streams. In this implementation, we are
@@ -457,19 +639,10 @@
         // Build up the hash tables to look up Exif tags for reading Exif tags.
         for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
             sExifTagMapsForReading[hint] = new HashMap();
+            sExifTagMapsForWriting[hint] = new HashMap();
             for (ExifTag tag : EXIF_TAGS[hint]) {
                 sExifTagMapsForReading[hint].put(tag.number, tag.name);
-            }
-        }
-
-        // Build up the hash tables to look up Exif tags for writing Exif tags.
-        // There are some tags that have the same tag name in the different group. For that tags,
-        // Primary image TIFF IFD and Exif private IFD have a higher priority to map than the other
-        // tag groups. For the same tags, it writes one tag in the only one IFD group, which has the
-        // higher priority group.
-        for (int hint = EXIF_TAGS.length - 1; hint >= 0; --hint) {
-            for (ExifTag tag : EXIF_TAGS[hint]) {
-                sExifTagMapForWriting.put(tag.name, new Pair<>(tag.number, hint));
+                sExifTagMapsForWriting[hint].put(tag.name, tag.number);
             }
         }
     }
@@ -477,8 +650,8 @@
     private final String mFilename;
     private final FileDescriptor mSeekableFileDescriptor;
     private final AssetManager.AssetInputStream mAssetInputStream;
-    private final HashMap<String, String> mAttributes = new HashMap<>();
     private boolean mIsRaw;
+    private final HashMap[] mAttributes = new HashMap[EXIF_TAGS.length];
     private boolean mHasThumbnail;
     // The following values used for indicating a thumbnail position.
     private int mThumbnailOffset;
@@ -554,7 +727,15 @@
      * @param tag the name of the tag.
      */
     public String getAttribute(String tag) {
-        return mAttributes.get(tag);
+        // Retrieves all tag groups. The value from primary image tag group has a higher priority
+        // than the value from the thumbnail tag group if there are more than one candidates.
+        for (int i = 0; i < EXIF_TAGS.length; ++i) {
+            Object value = mAttributes[i].get(tag);
+            if (value != null) {
+                return (String) value;
+            }
+        }
+        return null;
     }
 
     /**
@@ -566,11 +747,11 @@
      * @param defaultValue the value to return if the tag is not available.
      */
     public int getAttributeInt(String tag, int defaultValue) {
-        String value = mAttributes.get(tag);
+        String value = getAttribute(tag);
         if (value == null) return defaultValue;
         try {
             return Integer.valueOf(value);
-        } catch (NumberFormatException ex) {
+        } catch (NumberFormatException e) {
             return defaultValue;
         }
     }
@@ -584,7 +765,7 @@
      * @param defaultValue the value to return if the tag is not available.
      */
     public double getAttributeDouble(String tag, double defaultValue) {
-        String value = mAttributes.get(tag);
+        String value = getAttribute(tag);
         if (value == null) return defaultValue;
         try {
             int index = value.indexOf("/");
@@ -593,7 +774,7 @@
             if (denom == 0) return defaultValue;
             double num = Double.parseDouble(value.substring(0, index));
             return num / denom;
-        } catch (NumberFormatException ex) {
+        } catch (NumberFormatException e) {
             return defaultValue;
         }
     }
@@ -605,11 +786,11 @@
      * @param value the value of the tag.
      */
     public void setAttribute(String tag, String value) {
-        if (value == null) {
-            mAttributes.remove(tag);
-            return;
+        for (int i = 0 ; i < EXIF_TAGS.length; ++i) {
+            if (sExifTagMapsForWriting[i].containsKey(tag)) {
+                mAttributes[i].put(tag, value);
+            }
         }
-        mAttributes.put(tag, value);
     }
 
     /**
@@ -618,6 +799,11 @@
      * determine whether the image data format is JPEG or not.
      */
     private void loadAttributes(@NonNull InputStream in) throws IOException {
+        // Initialize mAttributes.
+        for (int i = 0; i < EXIF_TAGS.length; ++i) {
+            mAttributes[i] = new HashMap();
+        }
+
         // Process RAW input stream
         if (mAssetInputStream != null) {
             long asset = mAssetInputStream.getNativeAsset();
@@ -638,7 +824,13 @@
         }
 
         // Process JPEG input stream
-        getJpegAttributes(in);
+        try {
+            getJpegAttributes(in);
+        } catch (IOException e) {
+            // Ignore exceptions in order to keep the compatibility with the old versions of
+            // ExifInterface.
+            Log.w(TAG, "Invalid JPEG", e);
+        }
 
         if (DEBUG) {
             printAttributes();
@@ -664,8 +856,7 @@
         // Mark for disabling the save feature.
         mIsRaw = true;
 
-        for (Object obj : map.entrySet()) {
-            Map.Entry entry = (Map.Entry) obj;
+        for (Map.Entry entry : (Set<Map.Entry>) map.entrySet()) {
             String attrName = (String) entry.getKey();
 
             switch (attrName) {
@@ -682,7 +873,7 @@
                     mThumbnailBytes = (byte[]) entry.getValue();
                     break;
                 default:
-                    mAttributes.put(attrName, (String) entry.getValue());
+                    setAttribute(attrName, (String) entry.getValue());
                     break;
             }
         }
@@ -704,9 +895,11 @@
 
     // Prints out attributes for debugging.
     private void printAttributes() {
-        Log.d(TAG, "The size of tags: " + mAttributes.size());
-        for (Map.Entry<String, String> entry : mAttributes.entrySet()) {
-            Log.d(TAG, "tagName: " + entry.getKey() + ", tagValue: " + entry.getValue());
+        for (int i = 0; i < mAttributes.length; ++i) {
+            Log.d(TAG, "The size of tag group[" + i + "]: " + mAttributes[i].size());
+            for (Map.Entry entry : (Set<Map.Entry>) mAttributes[i].entrySet()) {
+                Log.d(TAG, "tagName: " + entry.getKey() + ", tagValue: " + entry.getValue());
+            }
         }
     }
 
@@ -851,10 +1044,10 @@
      * Exif tags are not available.
      */
     public boolean getLatLong(float output[]) {
-        String latValue = mAttributes.get(TAG_GPS_LATITUDE);
-        String latRef = mAttributes.get(TAG_GPS_LATITUDE_REF);
-        String lngValue = mAttributes.get(TAG_GPS_LONGITUDE);
-        String lngRef = mAttributes.get(TAG_GPS_LONGITUDE_REF);
+        String latValue = getAttribute(TAG_GPS_LATITUDE);
+        String latRef = getAttribute(TAG_GPS_LATITUDE_REF);
+        String lngValue = getAttribute(TAG_GPS_LONGITUDE);
+        String lngRef = getAttribute(TAG_GPS_LONGITUDE_REF);
 
         if (latValue != null && latRef != null && lngValue != null && lngRef != null) {
             try {
@@ -892,7 +1085,7 @@
      * @hide
      */
     public long getDateTime() {
-        String dateTimeString = mAttributes.get(TAG_DATETIME);
+        String dateTimeString = getAttribute(TAG_DATETIME);
         if (dateTimeString == null
                 || !sNonZeroTimePattern.matcher(dateTimeString).matches()) return -1;
 
@@ -904,7 +1097,7 @@
             if (datetime == null) return -1;
             long msecs = datetime.getTime();
 
-            String subSecs = mAttributes.get(TAG_SUBSECTIME);
+            String subSecs = getAttribute(TAG_SUBSECTIME);
             if (subSecs != null) {
                 try {
                     long sub = Long.valueOf(subSecs);
@@ -917,7 +1110,7 @@
                 }
             }
             return msecs;
-        } catch (IllegalArgumentException ex) {
+        } catch (IllegalArgumentException e) {
             return -1;
         }
     }
@@ -928,8 +1121,8 @@
      * @hide
      */
     public long getGpsDateTime() {
-        String date = mAttributes.get(TAG_GPS_DATESTAMP);
-        String time = mAttributes.get(TAG_GPS_TIMESTAMP);
+        String date = getAttribute(TAG_GPS_DATESTAMP);
+        String time = getAttribute(TAG_GPS_TIMESTAMP);
         if (date == null || time == null
                 || (!sNonZeroTimePattern.matcher(date).matches()
                 && !sNonZeroTimePattern.matcher(time).matches())) return -1;
@@ -941,7 +1134,7 @@
             Date datetime = sFormatter.parse(dateTimeString, pos);
             if (datetime == null) return -1;
             return datetime.getTime();
-        } catch (IllegalArgumentException ex) {
+        } catch (IllegalArgumentException e) {
             return -1;
         }
     }
@@ -1010,8 +1203,9 @@
             }
             bytesRead += 2;
             int length = dataInputStream.readUnsignedShort() - 2;
-            if (length < 0)
+            if (length < 0) {
                 throw new IOException("Invalid length");
+            }
             bytesRead += length;
             switch (marker) {
                 case MARKER_APP1: {
@@ -1034,6 +1228,9 @@
                     if (length <= 0) {
                         throw new IOException("Invalid exif");
                     }
+                    if (DEBUG) {
+                        Log.d(TAG, "readExifSegment with a byte array (length: " + length + ")");
+                    }
                     byte[] bytes = new byte[length];
                     if (dataInputStream.read(bytes) != length) {
                         throw new IOException("Invalid exif");
@@ -1049,8 +1246,7 @@
                     if (dataInputStream.read(bytes) != length) {
                         throw new IOException("Invalid exif");
                     }
-                    mAttributes.put("UserComment",
-                            new String(bytes, Charset.forName("US-ASCII")));
+                    setAttribute("UserComment", new String(bytes, Charset.forName("US-ASCII")));
                     break;
                 }
 
@@ -1068,10 +1264,9 @@
                 case MARKER_SOF14:
                 case MARKER_SOF15: {
                     dataInputStream.skipBytes(1);
-                    mAttributes.put("ImageLength",
+                    setAttribute("ImageLength",
                             String.valueOf(dataInputStream.readUnsignedShort()));
-                    mAttributes.put("ImageWidth",
-                            String.valueOf(dataInputStream.readUnsignedShort()));
+                    setAttribute("ImageWidth", String.valueOf(dataInputStream.readUnsignedShort()));
                     length -= 5;
                     break;
                 }
@@ -1124,8 +1319,9 @@
                 case MARKER_APP1: {
                     // Rewrite EXIF segment
                     int length = dataInputStream.readUnsignedShort() - 2;
-                    if (length < 0)
+                    if (length < 0) {
                         throw new IOException("Invalid length");
+                    }
                     bytesRead += 2;
                     int read;
                     while ((read = dataInputStream.read(
@@ -1146,8 +1342,9 @@
                     // Copy JPEG segment
                     int length = dataInputStream.readUnsignedShort();
                     dataOutputStream.writeUnsignedShort(length);
-                    if (length < 0)
+                    if (length < 0) {
                         throw new IOException("Invalid length");
+                    }
                     length -= 2;
                     bytesRead += 2;
                     int read;
@@ -1200,47 +1397,53 @@
         }
         firstIfdOffset -= 8;
         if (firstIfdOffset > 0) {
-            if (dataInputStream.skip(firstIfdOffset) != firstIfdOffset)
+            if (dataInputStream.skip(firstIfdOffset) != firstIfdOffset) {
                 throw new IOException("Couldn't jump to first Ifd: " + firstIfdOffset);
+            }
         }
 
         // Read primary image TIFF image file directory.
         readImageFileDirectory(dataInputStream, IFD_TIFF_HINT);
 
         // Process thumbnail.
-        try {
-            int jpegInterchangeFormat = Integer.parseInt(
-                    mAttributes.get(JPEG_INTERCHANGE_FORMAT_TAG.name));
-            int jpegInterchangeFormatLength = Integer.parseInt(
-                    mAttributes.get(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name));
-            // The following code limits the size of thumbnail size not to overflow EXIF data area.
-            jpegInterchangeFormatLength = Math.min(jpegInterchangeFormat
-                    + jpegInterchangeFormatLength, exifOffsetFromBeginning + exifBytes.length)
-                    - jpegInterchangeFormat;
-            if (jpegInterchangeFormat > 0 && jpegInterchangeFormatLength > 0) {
-                mHasThumbnail = true;
-                mThumbnailOffset = exifOffsetFromBeginning + jpegInterchangeFormat;
-                mThumbnailLength = jpegInterchangeFormatLength;
+        String jpegInterchangeFormatString = getAttribute(JPEG_INTERCHANGE_FORMAT_TAG.name);
+        String jpegInterchangeFormatLengthString =
+                getAttribute(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name);
+        if (jpegInterchangeFormatString != null && jpegInterchangeFormatLengthString != null) {
+            try {
+                int jpegInterchangeFormat = Integer.parseInt(jpegInterchangeFormatString);
+                int jpegInterchangeFormatLength = Integer
+                        .parseInt(jpegInterchangeFormatLengthString);
+                // The following code limits the size of thumbnail size not to overflow EXIF data area.
+                jpegInterchangeFormatLength = Math.min(jpegInterchangeFormat
+                        + jpegInterchangeFormatLength, exifOffsetFromBeginning + exifBytes.length)
+                        - jpegInterchangeFormat;
+                if (jpegInterchangeFormat > 0 && jpegInterchangeFormatLength > 0) {
+                    mHasThumbnail = true;
+                    mThumbnailOffset = exifOffsetFromBeginning + jpegInterchangeFormat;
+                    mThumbnailLength = jpegInterchangeFormatLength;
 
-                if (mFilename == null && mAssetInputStream == null
-                        && mSeekableFileDescriptor == null) {
-                    // Save the thumbnail in memory if the input doesn't support reading again.
-                    byte[] thumbnailBytes = new byte[jpegInterchangeFormatLength];
-                    dataInputStream.seek(jpegInterchangeFormat);
-                    dataInputStream.readFully(thumbnailBytes);
-                    mThumbnailBytes = thumbnailBytes;
+                    if (mFilename == null && mAssetInputStream == null
+                            && mSeekableFileDescriptor == null) {
+                        // Save the thumbnail in memory if the input doesn't support reading again.
+                        byte[] thumbnailBytes = new byte[jpegInterchangeFormatLength];
+                        dataInputStream.seek(jpegInterchangeFormat);
+                        dataInputStream.readFully(thumbnailBytes);
+                        mThumbnailBytes = thumbnailBytes;
 
-                    if (DEBUG) {
-                        Bitmap bitmap = BitmapFactory.decodeByteArray(
-                                thumbnailBytes, 0, thumbnailBytes.length);
-                        Log.d(TAG, "Thumbnail offset: " + mThumbnailOffset + ", length: "
-                                + mThumbnailLength + ", width: " + bitmap.getWidth() + ", height: "
-                                + bitmap.getHeight());
+                        if (DEBUG) {
+                            Bitmap bitmap = BitmapFactory.decodeByteArray(
+                                    thumbnailBytes, 0, thumbnailBytes.length);
+                            Log.d(TAG, "Thumbnail offset: " + mThumbnailOffset + ", length: "
+                                    + mThumbnailLength + ", width: " + bitmap.getWidth()
+                                    + ", height: "
+                                    + bitmap.getHeight());
+                        }
                     }
                 }
+            } catch (NumberFormatException e) {
+                // Ignored the corrupted image.
             }
-        } catch (NumberFormatException e) {
-            // Ignored the corrupted image.
         }
 
         // For compatibility, keep data formats as follows.
@@ -1251,7 +1454,7 @@
         convertToRational(TAG_FOCAL_LENGTH);
         convertToDouble(TAG_DIGITAL_ZOOM_RATIO);
         convertToDouble(TAG_EXPOSURE_TIME);
-        convertToDouble(TAG_APERTURE);
+        convertToDouble(TAG_F_NUMBER);
         convertToDouble(TAG_SUBJECT_DISTANCE);
         convertToInt(TAG_ISO);
         convertToDouble(TAG_EXPOSURE_BIAS_VALUE);
@@ -1267,29 +1470,29 @@
         convertToTimetamp(TAG_GPS_TIMESTAMP);
 
         // The value of DATETIME tag has the same value of DATETIME_ORIGINAL tag.
-        String valueOfDateTimeOriginal = mAttributes.get("DateTimeOriginal");
+        String valueOfDateTimeOriginal = getAttribute("DateTimeOriginal");
         if (valueOfDateTimeOriginal != null) {
-            mAttributes.put(TAG_DATETIME, valueOfDateTimeOriginal);
+            setAttribute(TAG_DATETIME, valueOfDateTimeOriginal);
         }
 
         // Add the default value.
-        if (!mAttributes.containsKey(TAG_IMAGE_WIDTH)) {
-            mAttributes.put(TAG_IMAGE_WIDTH, "0");
+        if (getAttribute(TAG_IMAGE_WIDTH) == null) {
+            setAttribute(TAG_IMAGE_WIDTH, "0");
         }
-        if (!mAttributes.containsKey(TAG_IMAGE_LENGTH)) {
-            mAttributes.put(TAG_IMAGE_LENGTH, "0");
+        if (getAttribute(TAG_IMAGE_LENGTH) == null) {
+            setAttribute(TAG_IMAGE_LENGTH, "0");
         }
-        if (!mAttributes.containsKey(TAG_ORIENTATION)) {
-            mAttributes.put(TAG_ORIENTATION, "0");
+        if (getAttribute(TAG_ORIENTATION) == null) {
+            setAttribute(TAG_ORIENTATION, "0");
         }
-        if (!mAttributes.containsKey(TAG_LIGHT_SOURCE)) {
-            mAttributes.put(TAG_LIGHT_SOURCE, "0");
+        if (getAttribute(TAG_LIGHT_SOURCE) == null) {
+            setAttribute(TAG_LIGHT_SOURCE, "0");
         }
     }
 
     // Converts the tag value to timestamp; Otherwise deletes the given tag.
     private void convertToTimetamp(String tagName) {
-        String entryValue = mAttributes.get(tagName);
+        String entryValue = getAttribute(tagName);
         if (entryValue == null) return;
         int dataFormat = getDataFormatOfExifEntryValue(entryValue);
         String[] components = entryValue.split(",");
@@ -1309,16 +1512,16 @@
                 int value = numerator / denominator;
                 stringBuilder.append(String.format("%02d", value));
             }
-            mAttributes.put(tagName, stringBuilder.toString());
+            setAttribute(tagName, stringBuilder.toString());
         } else if (dataFormat != IFD_FORMAT_STRING) {
-            mAttributes.remove(tagName);
+            setAttribute(tagName, null);
         }
     }
 
     // Checks the tag value of a given tag formatted in double type; Otherwise try to convert it to
     // double type or delete it.
     private void convertToDouble(String tagName) {
-        String entryValue = mAttributes.get(tagName);
+        String entryValue = getAttribute(tagName);
         if (entryValue == null) return;
         int dataFormat = getDataFormatOfExifEntryValue(entryValue);
         switch (dataFormat) {
@@ -1338,21 +1541,21 @@
                     }
                     stringBuilder.append((double) numerator / denominator);
                 }
-                mAttributes.put(tagName, stringBuilder.toString());
+                setAttribute(tagName, stringBuilder.toString());
                 break;
             }
             case IFD_FORMAT_DOUBLE:
                 // Keep it as is.
                 break;
             default:
-                mAttributes.remove(tagName);
+                setAttribute(tagName, null);
                 break;
         }
     }
 
     // Checks the tag value of a given tag formatted in int type; Otherwise deletes the tag value.
     private void convertToRational(String tagName) {
-        String entryValue = mAttributes.get(tagName);
+        String entryValue = getAttribute(tagName);
         if (entryValue == null) return;
         int dataFormat = getDataFormatOfExifEntryValue(entryValue);
         switch (dataFormat) {
@@ -1367,33 +1570,41 @@
                     double doubleValue = Double.parseDouble(component);
                     stringBuilder.append((int) (doubleValue * 10000.0)).append("/").append(10000);
                 }
-                mAttributes.put(tagName, stringBuilder.toString());
+                setAttribute(tagName, stringBuilder.toString());
                 break;
             }
             case IFD_FORMAT_SRATIONAL:
                 // Keep it as is.
                 break;
             default:
-                mAttributes.remove(tagName);
+                setAttribute(tagName, null);
                 break;
         }
     }
 
     // Checks the tag value of a given tag formatted in int type; Otherwise deletes the tag value.
     private void convertToInt(String tagName) {
-        String entryValue = mAttributes.get(tagName);
+        String entryValue = getAttribute(tagName);
         if (entryValue == null) return;
         int dataFormat = getDataFormatOfExifEntryValue(entryValue);
         if (dataFormat != IFD_FORMAT_SLONG) {
-            mAttributes.remove(tagName);
+            setAttribute(tagName, null);
         }
     }
 
     // Reads image file directory, which is a tag group in EXIF.
     private void readImageFileDirectory(ByteOrderAwarenessDataInputStream dataInputStream, int hint)
             throws IOException {
+        if (dataInputStream.peek() + 2 > dataInputStream.mLength) {
+            // Return if there is no data from the offset.
+            return;
+        }
         // See JEITA CP-3451 Figure 5. page 9.
         short numberOfDirectoryEntry = dataInputStream.readShort();
+        if (dataInputStream.peek() + 12 * numberOfDirectoryEntry > dataInputStream.mLength) {
+            // Return if the size of entries is too big.
+            return;
+        }
 
         if (DEBUG) {
             Log.d(TAG, "numberOfDirectoryEntry: " + numberOfDirectoryEntry);
@@ -1405,10 +1616,25 @@
             int numberOfComponents = dataInputStream.readInt();
             long nextEntryOffset = dataInputStream.peek() + 4;  // next four bytes is for data
                                                                 // offset or value.
+            // Look up a corresponding tag from tag number
+            String tagName = (String) sExifTagMapsForReading[hint].get(tagNumber);
 
             if (DEBUG) {
-                Log.d(TAG, String.format("tagNumber: %d, dataFormat: %d, numberOfComponents: %d",
-                        tagNumber, dataFormat, numberOfComponents));
+                Log.d(TAG, String.format("hint: %d, tagNumber: %d, tagName: %s, dataFormat: %d," +
+                        "numberOfComponents: %d", hint, tagNumber, tagName, dataFormat,
+                        numberOfComponents));
+            }
+
+            if (tagName == null || dataFormat <= 0 ||
+                    dataFormat >= IFD_FORMAT_BYTES_PER_FORMAT.length) {
+                // Skip if the parsed tag number is not defined or invalid data format.
+                if (tagName == null) {
+                    Log.w(TAG, "Skip the tag entry since tag number is not defined: " + tagNumber);
+                } else {
+                    Log.w(TAG, "Skip the tag entry since data format is invalid: " + dataFormat);
+                }
+                dataInputStream.seek(nextEntryOffset);
+                continue;
             }
 
             // Read a value from data field or seek to the value offset which is stored in data
@@ -1419,19 +1645,21 @@
                 if (DEBUG) {
                     Log.d(TAG, "seek to data offset: " + offset);
                 }
-                dataInputStream.seek(offset);
-            }
-
-            // Look up a corresponding tag from tag number
-            String tagName = (String) sExifTagMapsForReading[hint].get(tagNumber);
-            // Skip if the parsed tag number is not defined.
-            if (tagName == null) {
-                dataInputStream.seek(nextEntryOffset);
-                continue;
+                if (offset + byteCount <= dataInputStream.mLength) {
+                    dataInputStream.seek(offset);
+                } else {
+                     // Skip if invalid data offset.
+                    Log.w(TAG, "Skip the tag entry since data offset is invalid: " + offset);
+                    dataInputStream.seek(nextEntryOffset);
+                    continue;
+                }
             }
 
             // Recursively parse IFD when a IFD pointer tag appears.
             int innerIfdHint = getIfdHintFromTagNumber(tagNumber);
+            if (DEBUG) {
+                Log.d(TAG, "innerIfdHint: " + innerIfdHint + " byteCount: " + byteCount);
+            }
             if (innerIfdHint >= 0) {
                 long offset = -1L;
                 // Get offset from data field
@@ -1460,9 +1688,11 @@
                 if (DEBUG) {
                     Log.d(TAG, String.format("Offset: %d, tagName: %s", offset, tagName));
                 }
-                if (offset > 0L) {
+                if (offset > 0L && offset < dataInputStream.mLength) {
                     dataInputStream.seek(offset);
                     readImageFileDirectory(dataInputStream, innerIfdHint);
+                } else {
+                    Log.w(TAG, "Skip jump into the IFD since its offset is invalid: " + offset);
                 }
 
                 dataInputStream.seek(nextEntryOffset);
@@ -1474,7 +1704,7 @@
                 String entryValue = readExifEntryValue(
                         dataInputStream, dataFormat, numberOfComponents);
                 if (entryValue != null) {
-                    mAttributes.put(tagName, entryValue);
+                    setAttribute(tagName, entryValue);
                 }
             } else {
                 StringBuilder entryValueBuilder = new StringBuilder();
@@ -1485,7 +1715,7 @@
                     entryValueBuilder.append(readExifEntryValue(
                             dataInputStream, dataFormat, numberOfComponents));
                 }
-                mAttributes.put(tagName, entryValueBuilder.toString());
+                setAttribute(tagName, entryValueBuilder.toString());
             }
 
             if (dataInputStream.peek() != nextEntryOffset) {
@@ -1493,14 +1723,17 @@
             }
         }
 
-        long nextIfdOffset = dataInputStream.readUnsignedInt();
-        if (DEBUG) {
-            Log.d(TAG, String.format("nextIfdOffset: %d", nextIfdOffset));
-        }
-        // The next IFD offset needs to be bigger than 8 since the first IFD offset is at least 8.
-        if (nextIfdOffset > 8) {
-            dataInputStream.seek(nextIfdOffset);
-            readImageFileDirectory(dataInputStream, IFD_THUMBNAIL_HINT);
+        if (dataInputStream.peek() + 4 <= dataInputStream.mLength) {
+            long nextIfdOffset = dataInputStream.readUnsignedInt();
+            if (DEBUG) {
+                Log.d(TAG, String.format("nextIfdOffset: %d", nextIfdOffset));
+            }
+            // The next IFD offset needs to be bigger than 8
+            // since the first IFD offset is at least 8.
+            if (nextIfdOffset > 8 && nextIfdOffset < dataInputStream.mLength) {
+                dataInputStream.seek(nextIfdOffset);
+                readImageFileDirectory(dataInputStream, IFD_THUMBNAIL_HINT);
+            }
         }
     }
 
@@ -1558,19 +1791,18 @@
                 }
 
                 StringBuilder stringBuilder = new StringBuilder();
-                while (true) {
+                while (index < numberOfComponents) {
                     int ch = bytes[index];
-                    if (ch < 0)
-                        throw new EOFException();
-                    if (ch == 0)
+                    if (ch == 0) {
                         break;
-                    if (ch >= 32)
+                    }
+                    if (ch >= 32) {
                         stringBuilder.append((char) ch);
-                    else
+                    }
+                    else {
                         stringBuilder.append('?');
+                    }
                     ++index;
-                    if (index == numberOfComponents)
-                        break;
                 }
                 return stringBuilder.toString();
             }
@@ -1584,8 +1816,9 @@
     // Gets the corresponding IFD group index of the given tag number for writing Exif Tags.
     private static int getIfdHintFromTagNumber(int tagNumber) {
         for (int i = 0; i < IFD_POINTER_TAG_HINTS.length; ++i) {
-            if (IFD_POINTER_TAGS[i].number == tagNumber)
+            if (IFD_POINTER_TAGS[i].number == tagNumber) {
                 return IFD_POINTER_TAG_HINTS[i];
+            }
         }
         return -1;
     }
@@ -1597,49 +1830,46 @@
         int[] ifdOffsets = new int[EXIF_TAGS.length];
         int[] ifdDataSizes = new int[EXIF_TAGS.length];
 
-        // Maps to store tags per IFD tag group
-        HashMap[] ifdTags = new HashMap[EXIF_TAGS.length];
-        for (int i = 0; i < EXIF_TAGS.length; ++i) {
-            ifdTags[i] = new HashMap();
-        }
-
         // Remove IFD pointer tags (we'll re-add it later.)
         for (ExifTag tag : IFD_POINTER_TAGS) {
-            mAttributes.remove(tag.name);
-        }
-
-        // Assign tags to the corresponding group
-        for (Map.Entry<String, String> entry : mAttributes.entrySet()) {
-            Pair<Integer, Integer> pair = sExifTagMapForWriting.get(entry.getKey());
-            if (pair != null) {
-                int tagNumber = pair.first;
-                int hint = pair.second;
-                ifdTags[hint].put(tagNumber, entry.getValue());
-            }
+            setAttribute(tag.name, null);
         }
 
         // Add IFD pointer tags. The next offset of primary image TIFF IFD will have thumbnail IFD
         // offset when there is one or more tags in the thumbnail IFD.
-        if (!ifdTags[IFD_INTEROPERABILITY_HINT].isEmpty()) {
-            ifdTags[IFD_EXIF_HINT].put(IFD_POINTER_TAGS[2].number, "0");
+        if (!mAttributes[IFD_INTEROPERABILITY_HINT].isEmpty()) {
+            mAttributes[IFD_EXIF_HINT].put(IFD_POINTER_TAGS[2].name, "0");
         }
-        if (!ifdTags[IFD_EXIF_HINT].isEmpty()) {
-            ifdTags[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[0].number, "0");
+        if (!mAttributes[IFD_EXIF_HINT].isEmpty()) {
+            mAttributes[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[0].name, "0");
         }
-        if (!ifdTags[IFD_GPS_HINT].isEmpty()) {
-            ifdTags[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[1].number, "0");
+        if (!mAttributes[IFD_GPS_HINT].isEmpty()) {
+            mAttributes[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[1].name, "0");
         }
+        // Remove old thumbnail data
+        setAttribute(JPEG_INTERCHANGE_FORMAT_TAG.name, null);
+        setAttribute(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name, null);
         if (mHasThumbnail) {
-            ifdTags[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.number, "0");
-            ifdTags[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.number,
+            mAttributes[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.name, "0");
+            mAttributes[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name,
                     String.valueOf(mThumbnailLength));
         }
 
+        // Remove null value tags.
+        for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
+            for (Object obj : mAttributes[hint].entrySet().toArray()) {
+                Map.Entry entry = (Map.Entry) obj;
+                if (entry.getValue() == null) {
+                    mAttributes[hint].remove(entry.getKey());
+                }
+            }
+        }
+
         // Calculate IFD group data area sizes. IFD group data area is assigned to save the entry
         // value which has a bigger size than 4 bytes.
         for (int i = 0; i < 5; ++i) {
             int sum = 0;
-            for (Object entry : ifdTags[i].entrySet()) {
+            for (Map.Entry entry : (Set<Map.Entry>) mAttributes[i].entrySet()) {
                 String entryValue = (String) ((Map.Entry) entry).getValue();
                 int dataFormat = getDataFormatOfExifEntryValue(entryValue);
                 int size = getSizeOfExifEntryValue(dataFormat, entryValue);
@@ -1653,16 +1883,16 @@
         // Calculate IFD offsets.
         int position = 8;
         for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
-            if (!ifdTags[hint].isEmpty()) {
+            if (!mAttributes[hint].isEmpty()) {
                 ifdOffsets[hint] = position;
-                position += 2 + ifdTags[hint].size() * 12 + 4 + ifdDataSizes[hint];
+                position += 2 + mAttributes[hint].size() * 12 + 4 + ifdDataSizes[hint];
             }
         }
         if (mHasThumbnail) {
             int thumbnailOffset = position;
-            ifdTags[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.number,
+            mAttributes[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.name,
                     String.valueOf(thumbnailOffset));
-            ifdTags[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.number,
+            mAttributes[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name,
                     String.valueOf(mThumbnailLength));
             mThumbnailOffset = exifOffsetFromBeginning + thumbnailOffset;
             position += mThumbnailLength;
@@ -1674,21 +1904,21 @@
             Log.d(TAG, "totalSize length: " + totalSize);
             for (int i = 0; i < 5; ++i) {
                 Log.d(TAG, String.format("index: %d, offsets: %d, tag count: %d, data sizes: %d",
-                        i, ifdOffsets[i], ifdTags[i].size(), ifdDataSizes[i]));
+                        i, ifdOffsets[i], mAttributes[i].size(), ifdDataSizes[i]));
             }
         }
 
         // Update IFD pointer tags with the calculated offsets.
-        if (!ifdTags[IFD_EXIF_HINT].isEmpty()) {
-            ifdTags[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[0].number,
+        if (!mAttributes[IFD_EXIF_HINT].isEmpty()) {
+            mAttributes[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[0].name,
                     String.valueOf(ifdOffsets[IFD_EXIF_HINT]));
         }
-        if (!ifdTags[IFD_GPS_HINT].isEmpty()) {
-            ifdTags[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[1].number,
+        if (!mAttributes[IFD_GPS_HINT].isEmpty()) {
+            mAttributes[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[1].name,
                     String.valueOf(ifdOffsets[IFD_GPS_HINT]));
         }
-        if (!ifdTags[IFD_INTEROPERABILITY_HINT].isEmpty()) {
-            ifdTags[IFD_EXIF_HINT].put(IFD_POINTER_TAGS[2].number,
+        if (!mAttributes[IFD_INTEROPERABILITY_HINT].isEmpty()) {
+            mAttributes[IFD_EXIF_HINT].put(IFD_POINTER_TAGS[2].name,
                     String.valueOf(ifdOffsets[IFD_INTEROPERABILITY_HINT]));
         }
 
@@ -1701,16 +1931,16 @@
 
         // Write IFD groups. See JEITA CP-3451C Figure 7. page 12.
         for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
-            if (!ifdTags[hint].isEmpty()) {
+            if (!mAttributes[hint].isEmpty()) {
                 // See JEITA CP-3451C 4.6.2 IFD structure. page 13.
                 // Write entry count
-                dataOutputStream.writeUnsignedShort(ifdTags[hint].size());
+                dataOutputStream.writeUnsignedShort(mAttributes[hint].size());
 
                 // Write entry info
-                int dataOffset = ifdOffsets[hint] + 2 + ifdTags[hint].size() * 12 + 4;
-                for (Object obj : ifdTags[hint].entrySet()) {
-                    Map.Entry entry = (Map.Entry) obj;
-                    int tagNumber = (int) entry.getKey();
+                int dataOffset = ifdOffsets[hint] + 2 + mAttributes[hint].size() * 12 + 4;
+                for (Map.Entry entry : (Set<Map.Entry>) mAttributes[hint].entrySet()) {
+                    // Convert tag name to tag number.
+                    int tagNumber = (int) sExifTagMapsForWriting[hint].get(entry.getKey());
                     String entryValue = (String) entry.getValue();
 
                     int dataFormat = getDataFormatOfExifEntryValue(entryValue);
@@ -1738,15 +1968,14 @@
                 // Write the next offset. It writes the offset of thumbnail IFD if there is one or
                 // more tags in the thumbnail IFD when the current IFD is the primary image TIFF
                 // IFD; Otherwise 0.
-                if (hint == 0 && !ifdTags[IFD_THUMBNAIL_HINT].isEmpty()) {
+                if (hint == 0 && !mAttributes[IFD_THUMBNAIL_HINT].isEmpty()) {
                     dataOutputStream.writeUnsignedInt(ifdOffsets[IFD_THUMBNAIL_HINT]);
                 } else {
                     dataOutputStream.writeUnsignedInt(0);
                 }
 
                 // Write values of data field exceeding 4 bytes after the next offset.
-                for (Object obj : ifdTags[hint].entrySet()) {
-                    Map.Entry entry = (Map.Entry) obj;
+                for (Map.Entry entry : (Set<Map.Entry>) mAttributes[hint].entrySet()) {
                     String entryValue = (String) entry.getValue();
 
                     int dataFormat = getDataFormatOfExifEntryValue(entryValue);
@@ -1892,8 +2121,9 @@
         public void seek(long byteCount) throws IOException {
             mPosition = 0L;
             reset();
-            if (skip(byteCount) != byteCount)
+            if (skip(byteCount) != byteCount) {
                 throw new IOException("Couldn't seek up to the byteCount");
+            }
         }
 
         public long peek() {
@@ -1902,8 +2132,9 @@
 
         public void readFully(byte[] buffer) throws IOException {
             mPosition += buffer.length;
-            if (mPosition > mLength)
+            if (mPosition > mLength) {
                 throw new EOFException();
+            }
             if (super.read(buffer, 0, buffer.length) != buffer.length) {
                 throw new IOException("Couldn't read up to the length of buffer");
             }
@@ -1911,22 +2142,26 @@
 
         public byte readByte() throws IOException {
             ++mPosition;
-            if (mPosition > mLength)
+            if (mPosition > mLength) {
                 throw new EOFException();
+            }
             int ch = super.read();
-            if (ch < 0)
+            if (ch < 0) {
                 throw new EOFException();
+            }
             return (byte) ch;
         }
 
         public short readShort() throws IOException {
             mPosition += 2;
-            if (mPosition > mLength)
+            if (mPosition > mLength) {
                 throw new EOFException();
+            }
             int ch1 = super.read();
             int ch2 = super.read();
-            if ((ch1 | ch2) < 0)
+            if ((ch1 | ch2) < 0) {
                 throw new EOFException();
+            }
             if (mByteOrder == LITTLE_ENDIAN) {
                 return (short) ((ch2 << 8) + (ch1));
             } else if (mByteOrder == BIG_ENDIAN) {
@@ -1937,14 +2172,16 @@
 
         public int readInt() throws IOException {
             mPosition += 4;
-            if (mPosition > mLength)
+            if (mPosition > mLength) {
                 throw new EOFException();
+            }
             int ch1 = super.read();
             int ch2 = super.read();
             int ch3 = super.read();
             int ch4 = super.read();
-            if ((ch1 | ch2 | ch3 | ch4) < 0)
+            if ((ch1 | ch2 | ch3 | ch4) < 0) {
                 throw new EOFException();
+            }
             if (mByteOrder == LITTLE_ENDIAN) {
                 return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + ch1);
             } else if (mByteOrder == BIG_ENDIAN) {
@@ -1962,12 +2199,14 @@
 
         public int readUnsignedShort() throws IOException {
             mPosition += 2;
-            if (mPosition > mLength)
+            if (mPosition > mLength) {
                 throw new EOFException();
+            }
             int ch1 = super.read();
             int ch2 = super.read();
-            if ((ch1 | ch2) < 0)
+            if ((ch1 | ch2) < 0) {
                 throw new EOFException();
+            }
             if (mByteOrder == LITTLE_ENDIAN) {
                 return ((ch2 << 8) + (ch1));
             } else if (mByteOrder == BIG_ENDIAN) {
@@ -1982,8 +2221,9 @@
 
         public long readLong() throws IOException {
             mPosition += 8;
-            if (mPosition > mLength)
+            if (mPosition > mLength) {
                 throw new EOFException();
+            }
             int ch1 = super.read();
             int ch2 = super.read();
             int ch3 = super.read();
@@ -1992,8 +2232,9 @@
             int ch6 = super.read();
             int ch7 = super.read();
             int ch8 = super.read();
-            if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0)
+            if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) {
                 throw new EOFException();
+            }
             if (mByteOrder == LITTLE_ENDIAN) {
                 return (((long) ch8 << 56) + ((long) ch7 << 48) + ((long) ch6 << 40)
                         + ((long) ch5 << 32) + ((long) ch4 << 24) + ((long) ch3 << 16)
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index db0c5bb..2650ee0 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -1070,16 +1070,15 @@
      * A CryptoSession is obtained using {@link #getCryptoSession}
      */
     public final class CryptoSession {
-        private MediaDrm mDrm;
         private byte[] mSessionId;
 
-        CryptoSession(@NonNull MediaDrm drm, @NonNull byte[] sessionId,
-                @NonNull String cipherAlgorithm, @NonNull String macAlgorithm)
+        CryptoSession(@NonNull byte[] sessionId,
+                      @NonNull String cipherAlgorithm,
+                      @NonNull String macAlgorithm)
         {
             mSessionId = sessionId;
-            mDrm = drm;
-            setCipherAlgorithmNative(drm, sessionId, cipherAlgorithm);
-            setMacAlgorithmNative(drm, sessionId, macAlgorithm);
+            setCipherAlgorithmNative(MediaDrm.this, sessionId, cipherAlgorithm);
+            setMacAlgorithmNative(MediaDrm.this, sessionId, macAlgorithm);
         }
 
         /**
@@ -1092,7 +1091,7 @@
         @NonNull
         public byte[] encrypt(
                 @NonNull byte[] keyid, @NonNull byte[] input, @NonNull byte[] iv) {
-            return encryptNative(mDrm, mSessionId, keyid, input, iv);
+            return encryptNative(MediaDrm.this, mSessionId, keyid, input, iv);
         }
 
         /**
@@ -1105,7 +1104,7 @@
         @NonNull
         public byte[] decrypt(
                 @NonNull byte[] keyid, @NonNull byte[] input, @NonNull byte[] iv) {
-            return decryptNative(mDrm, mSessionId, keyid, input, iv);
+            return decryptNative(MediaDrm.this, mSessionId, keyid, input, iv);
         }
 
         /**
@@ -1116,7 +1115,7 @@
          */
         @NonNull
         public byte[] sign(@NonNull byte[] keyid, @NonNull byte[] message) {
-            return signNative(mDrm, mSessionId, keyid, message);
+            return signNative(MediaDrm.this, mSessionId, keyid, message);
         }
 
         /**
@@ -1130,7 +1129,7 @@
          */
         public boolean verify(
                 @NonNull byte[] keyid, @NonNull byte[] message, @NonNull byte[] signature) {
-            return verifyNative(mDrm, mSessionId, keyid, message, signature);
+            return verifyNative(MediaDrm.this, mSessionId, keyid, message, signature);
         }
     };
 
@@ -1158,7 +1157,7 @@
             @NonNull byte[] sessionId,
             @NonNull String cipherAlgorithm, @NonNull String macAlgorithm)
     {
-        return new CryptoSession(this, sessionId, cipherAlgorithm, macAlgorithm);
+        return new CryptoSession(sessionId, cipherAlgorithm, macAlgorithm);
     }
 
     /**
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index a0e2481..26061e4 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -16,6 +16,10 @@
 
 package android.media;
 
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.nio.ByteBuffer;
 import java.util.HashMap;
 import java.util.Map;
@@ -606,6 +610,16 @@
     /** BT.2020 color chromacity coordinates with KR = 0.2627, KB = 0.0593. */
     public static final int COLOR_STANDARD_BT2020 = 6;
 
+    /** @hide */
+    @IntDef({
+        COLOR_STANDARD_BT709,
+        COLOR_STANDARD_BT601_PAL,
+        COLOR_STANDARD_BT601_NTSC,
+        COLOR_STANDARD_BT2020,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ColorStandard {}
+
     /**
      * An optional key describing the opto-electronic transfer function used
      * for the video content.
@@ -628,6 +642,16 @@
     /** ARIB STD-B67 hybrid-log-gamma transfer function. This is used by some HDR video content. */
     public static final int COLOR_TRANSFER_HLG = 7;
 
+    /** @hide */
+    @IntDef({
+        COLOR_TRANSFER_LINEAR,
+        COLOR_TRANSFER_SDR_VIDEO,
+        COLOR_TRANSFER_ST2084,
+        COLOR_TRANSFER_HLG,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ColorTransfer {}
+
     /**
      * An optional key describing the range of the component values of the video content.
      *
@@ -644,6 +668,26 @@
     /** Full range. Y, Cr and Cb component values range from 0 to 255 for 8-bit content. */
     public static final int COLOR_RANGE_FULL = 1;
 
+    /** @hide */
+    @IntDef({
+        COLOR_RANGE_LIMITED,
+        COLOR_RANGE_FULL,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ColorRange {}
+
+    /**
+     * An optional key describing the static metadata of HDR (high-dynamic-range) video content.
+     *
+     * The associated value is a ByteBuffer. This buffer contains the raw contents of the
+     * Static Metadata Descriptor (including the descriptor ID) of an HDMI Dynamic Range and
+     * Mastering InfoFrame as defined by CTA-861.3. This key must be provided to video decoders
+     * for HDR video content unless this information is contained in the bitstream and the video
+     * decoder supports an HDR-capable profile. This key must be provided to video encoders for
+     * HDR video content.
+     */
+    public static final String KEY_HDR_STATIC_INFO = "hdr-static-info";
+
     /**
      * A key describing a unique ID for the content of a media track.
      *
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 4977391..86ebae1 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -16,10 +16,6 @@
 
 package android.media;
 
-import com.android.internal.database.SortCursor;
-
-import libcore.io.Streams;
-
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.Activity;
@@ -32,12 +28,15 @@
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
-import android.os.RemoteException;
 import android.provider.MediaStore;
 import android.provider.Settings;
 import android.provider.Settings.System;
 import android.util.Log;
 
+import com.android.internal.database.SortCursor;
+
+import libcore.io.Streams;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -644,7 +643,8 @@
     public static Uri getActualDefaultRingtoneUri(Context context, int type) {
         String setting = getSettingForType(type);
         if (setting == null) return null;
-        final String uriString = Settings.System.getString(context.getContentResolver(), setting);
+        final String uriString = Settings.System.getStringForUser(context.getContentResolver(),
+                setting, context.getUserId());
         return uriString != null ? Uri.parse(uriString) : null;
     }
     
@@ -663,8 +663,8 @@
 
         String setting = getSettingForType(type);
         if (setting == null) return;
-        Settings.System.putString(resolver, setting,
-                ringtoneUri != null ? ringtoneUri.toString() : null);
+        Settings.System.putStringForUser(resolver, setting,
+                ringtoneUri != null ? ringtoneUri.toString() : null, context.getUserId());
 
         // Stream selected ringtone into cache so it's available for playback
         // when CE storage is still locked
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 55fb82b..adeb834 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -17,7 +17,9 @@
 package android.media.audiopolicy;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.media.AudioDeviceInfo;
 import android.media.AudioFormat;
 import android.media.AudioSystem;
 
@@ -34,21 +36,28 @@
     private AudioMixingRule mRule;
     private AudioFormat mFormat;
     private int mRouteFlags;
-    private String mRegistrationId;
     private int mMixType = MIX_TYPE_INVALID;
+
+    // written by AudioPolicy
     int mMixState = MIX_STATE_DISABLED;
     int mCallbackFlags;
+    String mDeviceAddress;
+
+    // initialized in constructor, read by AudioPolicyConfig
+    final int mDeviceSystemType; // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
 
     /**
      * All parameters are guaranteed valid through the Builder.
      */
-    private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags) {
+    private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags,
+            int deviceType, String deviceAddress) {
         mRule = rule;
         mFormat = format;
         mRouteFlags = routeFlags;
-        mRegistrationId = null;
         mMixType = rule.getTargetMixType();
         mCallbackFlags = callbackFlags;
+        mDeviceSystemType = deviceType;
+        mDeviceAddress = (deviceAddress == null) ? new String("") : deviceAddress;
     }
 
     // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined
@@ -74,6 +83,8 @@
     @SystemApi
     public static final int ROUTE_FLAG_LOOP_BACK = 0x1 << 1;
 
+    private static final int ROUTE_FLAG_SUPPORTED = ROUTE_FLAG_RENDER | ROUTE_FLAG_LOOP_BACK;
+
     // MIX_TYPE_* values to keep in sync with frameworks/av/include/media/AudioPolicy.h
     /**
      * @hide
@@ -142,12 +153,12 @@
     }
 
     void setRegistration(String regId) {
-        mRegistrationId = regId;
+        mDeviceAddress = regId;
     }
 
     /** @hide */
     public String getRegistration() {
-        return mRegistrationId;
+        return mDeviceAddress;
     }
 
     /** @hide */
@@ -172,6 +183,9 @@
         private AudioFormat mFormat = null;
         private int mRouteFlags = 0;
         private int mCallbackFlags = 0;
+        // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
+        private int mDeviceSystemType = AudioSystem.DEVICE_NONE;
+        private String mDeviceAddress = null;
 
         /**
          * @hide
@@ -200,7 +214,7 @@
          * @return the same Builder instance.
          * @throws IllegalArgumentException
          */
-        public Builder setMixingRule(AudioMixingRule rule)
+        Builder setMixingRule(AudioMixingRule rule)
                 throws IllegalArgumentException {
             if (rule == null) {
                 throw new IllegalArgumentException("Illegal null AudioMixingRule argument");
@@ -216,7 +230,7 @@
          * @return the same Builder instance.
          * @throws IllegalArgumentException
          */
-        public Builder setCallbackFlags(int flags) throws IllegalArgumentException {
+        Builder setCallbackFlags(int flags) throws IllegalArgumentException {
             if ((flags != 0) && ((flags & CALLBACK_FLAGS_ALL) == 0)) {
                 throw new IllegalArgumentException("Illegal callback flags 0x"
                         + Integer.toHexString(flags).toUpperCase());
@@ -226,6 +240,19 @@
         }
 
         /**
+         * @hide
+         * Only used by AudioPolicyConfig, not a public API.
+         * @param deviceType an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
+         * @param address
+         * @return the same Builder instance.
+         */
+        Builder setDevice(int deviceType, String address) {
+            mDeviceSystemType = deviceType;
+            mDeviceAddress = address;
+            return this;
+        }
+
+        /**
          * Sets the {@link AudioFormat} for the mix.
          * @param format a non-null {@link AudioFormat} instance.
          * @return the same Builder instance.
@@ -242,7 +269,8 @@
         }
 
         /**
-         * Sets the routing behavior for the mix.
+         * Sets the routing behavior for the mix. If not set, routing behavior will default to
+         * {@link AudioMix#ROUTE_FLAG_LOOP_BACK}.
          * @param routeFlags one of {@link AudioMix#ROUTE_FLAG_LOOP_BACK},
          *     {@link AudioMix#ROUTE_FLAG_RENDER}
          * @return the same Builder instance.
@@ -254,15 +282,41 @@
             if (routeFlags == 0) {
                 throw new IllegalArgumentException("Illegal empty route flags");
             }
-            if ((routeFlags & (ROUTE_FLAG_LOOP_BACK | ROUTE_FLAG_RENDER)) == 0) {
+            if ((routeFlags & ROUTE_FLAG_SUPPORTED) == 0) {
                 throw new IllegalArgumentException("Invalid route flags 0x"
-                        + Integer.toHexString(routeFlags) + "when creating an AudioMix");
+                        + Integer.toHexString(routeFlags) + "when configuring an AudioMix");
+            }
+            if ((routeFlags & ~ROUTE_FLAG_SUPPORTED) != 0) {
+                throw new IllegalArgumentException("Unknown route flags 0x"
+                        + Integer.toHexString(routeFlags) + "when configuring an AudioMix");
             }
             mRouteFlags = routeFlags;
             return this;
         }
 
         /**
+         * Sets the audio device used for playback. Cannot be used in the context of an audio
+         * policy used to inject audio to be recorded, or in a mix whose route flags doesn't
+         * specify {@link AudioMix#ROUTE_FLAG_RENDER}.
+         * @param device a non-null AudioDeviceInfo describing the audio device to play the output
+         *     of this mix.
+         * @return the same Builder instance
+         * @throws IllegalArgumentException
+         */
+        @SystemApi
+        public Builder setDevice(@NonNull AudioDeviceInfo device) throws IllegalArgumentException {
+            if (device == null) {
+                throw new IllegalArgumentException("Illegal null AudioDeviceInfo argument");
+            }
+            if (!device.isSink()) {
+                throw new IllegalArgumentException("Unsupported device type on mix, not a sink");
+            }
+            mDeviceSystemType = AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType());
+            mDeviceAddress = device.getAddress();
+            return this;
+        }
+
+        /**
          * Combines all of the settings and return a new {@link AudioMix} object.
          * @return a new {@link AudioMix} object
          * @throws IllegalArgumentException if no {@link AudioMixingRule} has been set.
@@ -273,8 +327,13 @@
                 throw new IllegalArgumentException("Illegal null AudioMixingRule");
             }
             if (mRouteFlags == 0) {
-                // no route flags set, use default
-                mRouteFlags = ROUTE_FLAG_RENDER;
+                // no route flags set, use default as described in Builder.setRouteFlags(int)
+                mRouteFlags = ROUTE_FLAG_LOOP_BACK;
+            }
+            // can't do loop back AND render at same time in this implementation
+            if (mRouteFlags == (ROUTE_FLAG_RENDER | ROUTE_FLAG_LOOP_BACK)) {
+                throw new IllegalArgumentException("Unsupported route behavior combination 0x" +
+                        Integer.toHexString(mRouteFlags));
             }
             if (mFormat == null) {
                 // FIXME Can we eliminate this?  Will AudioMix work with an unspecified sample rate?
@@ -284,7 +343,33 @@
                 }
                 mFormat = new AudioFormat.Builder().setSampleRate(rate).build();
             }
-            return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags);
+            if ((mDeviceSystemType != AudioSystem.DEVICE_NONE)
+                    && (mDeviceSystemType != AudioSystem.DEVICE_OUT_REMOTE_SUBMIX)
+                    && (mDeviceSystemType != AudioSystem.DEVICE_IN_REMOTE_SUBMIX)) {
+                if ((mRouteFlags & ROUTE_FLAG_RENDER) == 0) {
+                    throw new IllegalArgumentException(
+                            "Can't have audio device without flag ROUTE_FLAG_RENDER");
+                }
+                if (mRule.getTargetMixType() != AudioMix.MIX_TYPE_PLAYERS) {
+                    throw new IllegalArgumentException("Unsupported device on non-playback mix");
+                }
+            } else {
+                if ((mRouteFlags & ROUTE_FLAG_RENDER) == ROUTE_FLAG_RENDER) {
+                    throw new IllegalArgumentException(
+                            "Can't have flag ROUTE_FLAG_RENDER without an audio device");
+                }
+                if ((mRouteFlags & ROUTE_FLAG_SUPPORTED) == ROUTE_FLAG_LOOP_BACK) {
+                    if (mRule.getTargetMixType() == MIX_TYPE_PLAYERS) {
+                        mDeviceSystemType = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+                    } else if (mRule.getTargetMixType() == MIX_TYPE_RECORDERS) {
+                        mDeviceSystemType = AudioSystem.DEVICE_IN_REMOTE_SUBMIX;
+                    } else {
+                        throw new IllegalArgumentException("Unknown mixing rule type");
+                    }
+                }
+            }
+            return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceSystemType,
+                    mDeviceAddress);
         }
     }
 }
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index 5d2bac0..cafa5a8 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -17,6 +17,8 @@
 package android.media.audiopolicy;
 
 import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioPatch;
 import android.media.audiopolicy.AudioMixingRule.AudioMixMatchCriterion;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -81,6 +83,9 @@
             dest.writeInt(mix.getRouteFlags());
             // write callback flags
             dest.writeInt(mix.mCallbackFlags);
+            // write device information
+            dest.writeInt(mix.mDeviceSystemType);
+            dest.writeString(mix.mDeviceAddress);
             // write mix format
             dest.writeInt(mix.getFormat().getSampleRate());
             dest.writeInt(mix.getFormat().getEncoding());
@@ -104,6 +109,8 @@
             mixBuilder.setRouteFlags(routeFlags);
             // read callback flags
             mixBuilder.setCallbackFlags(in.readInt());
+            // read device information
+            mixBuilder.setDevice(in.readInt(), in.readString());
             // read mix format
             int sampleRate = in.readInt();
             int encoding = in.readInt();
@@ -197,8 +204,14 @@
         int mixIndex = 0;
         for (AudioMix mix : mMixes) {
             if (!mRegistrationId.isEmpty()) {
-                mix.setRegistration(mRegistrationId + "mix" + mixTypeId(mix.getMixType()) + ":"
-                        + mixIndex++);
+                if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_LOOP_BACK) ==
+                        AudioMix.ROUTE_FLAG_LOOP_BACK) {
+                    mix.setRegistration(mRegistrationId + "mix" + mixTypeId(mix.getMixType()) + ":"
+                            + mixIndex++);
+                } else if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_RENDER) ==
+                        AudioMix.ROUTE_FLAG_RENDER) {
+                    mix.setRegistration(mix.mDeviceAddress);
+                }
             } else {
                 mix.setRegistration("");
             }
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 0b0306c..89e4577 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.graphics.Rect;
 import android.media.PlaybackParams;
@@ -1241,6 +1242,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS)
     public void setParentalControlsEnabled(boolean enabled) {
         try {
             mService.setParentalControlsEnabled(enabled, mUserId);
@@ -1292,6 +1294,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS)
     public void addBlockedRating(@NonNull TvContentRating rating) {
         Preconditions.checkNotNull(rating);
         try {
@@ -1310,6 +1313,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS)
     public void removeBlockedRating(@NonNull TvContentRating rating) {
         Preconditions.checkNotNull(rating);
         try {
@@ -1444,6 +1448,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
     public List<TvInputHardwareInfo> getHardwareList() {
         try {
             return mService.getHardwareList();
@@ -1462,6 +1467,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
     public Hardware acquireTvInputHardware(int deviceId, final HardwareCallback callback,
             TvInputInfo info) {
         try {
@@ -1488,6 +1494,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
     public void releaseTvInputHardware(int deviceId, Hardware hardware) {
         try {
             mService.releaseTvInputHardware(deviceId, hardware.getInterface(), mUserId);
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index bc20c17..88be686 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -904,9 +904,7 @@
          *            i.e. prefixed with a package name you own, so that different developers will
          *            not create conflicting commands.
          * @param data Any data to include with the command.
-         * @hide
          */
-        @SystemApi
         public void onAppPrivateCommand(@NonNull String action, Bundle data) {
         }
 
@@ -1755,9 +1753,7 @@
          *            i.e. prefixed with a package name you own, so that different developers will
          *            not create conflicting commands.
          * @param data Any data to include with the command.
-         * @hide
          */
-        @SystemApi
         public void onAppPrivateCommand(@NonNull String action, Bundle data) {
         }
 
diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java
index d48ea21e..da1002d 100644
--- a/media/java/android/media/tv/TvRecordingClient.java
+++ b/media/java/android/media/tv/TvRecordingClient.java
@@ -200,16 +200,14 @@
     }
 
     /**
-     * Calls {@link TvInputService.RecordingSession#appPrivateCommand(String, Bundle)} for the
-     * current recording session.
+     * Sends a private command to the underlying TV input. This can be used to provide
+     * domain-specific features that are only known between certain clients and their TV inputs.
      *
      * @param action The name of the private command to send. This <em>must</em> be a scoped name,
      *            i.e. prefixed with a package name you own, so that different developers will not
      *            create conflicting commands.
      * @param data An optional bundle to send with the command.
-     * @hide
      */
-    @SystemApi
     public void sendAppPrivateCommand(@NonNull String action, Bundle data) {
         if (TextUtils.isEmpty(action)) {
             throw new IllegalArgumentException("action cannot be null or an empty string");
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 9623076..6ca6193c 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -293,7 +293,7 @@
 
     /**
      * Tunes to a given channel. This can be used to provide domain-specific features that are only
-     * known between certain TvView applications and their TV inputs.
+     * known between certain clients and their TV inputs.
      *
      * @param inputId The ID of TV input for the given channel.
      * @param channelUri The URI of a channel.
@@ -550,16 +550,14 @@
     }
 
     /**
-     * Calls {@link TvInputService.Session#onAppPrivateCommand(String, Bundle)} for the current
-     * session.
+     * Sends a private command to the underlying TV input. This can be used to provide
+     * domain-specific features that are only known between certain clients and their TV inputs.
      *
      * @param action The name of the private command to send. This <em>must</em> be a scoped name,
      *            i.e. prefixed with a package name you own, so that different developers will not
      *            create conflicting commands.
      * @param data An optional bundle to send with the command.
-     * @hide
      */
-    @SystemApi
     public void sendAppPrivateCommand(@NonNull String action, Bundle data) {
         if (TextUtils.isEmpty(action)) {
             throw new IllegalArgumentException("action cannot be null or an empty string");
diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index 527e6c2..62685c9 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -307,6 +307,11 @@
         AMessage::Type valueType;
         const char *key = msg->getEntryNameAt(i, &valueType);
 
+        if (!strncmp(key, "android._", 9)) {
+            // don't expose private keys (starting with android._)
+            continue;
+        }
+
         jobject valueObj = NULL;
 
         switch (valueType) {
@@ -460,6 +465,11 @@
         env->ReleaseStringUTFChars((jstring)keyObj, tmp);
         tmp = NULL;
 
+        if (key.startsWith("android._")) {
+            // don't propagate private keys (starting with android._)
+            continue;
+        }
+
         jobject valueObj = env->GetObjectArrayElement(values, i);
 
         if (env->IsInstanceOf(valueObj, stringClass.get())) {
@@ -735,8 +745,15 @@
         case HAL_PIXEL_FORMAT_BLOB:
             // Used for JPEG data, height must be 1, width == size, single plane.
             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
-            LOG_ALWAYS_FATAL_IF(buffer->height != 1,
-                    "BLOB format buffer should has height value %d", buffer->height);
+            // When RGBA override is being used, buffer height will be equal to width
+            if (usingRGBAOverride) {
+                LOG_ALWAYS_FATAL_IF(buffer->height != buffer->width,
+                        "RGBA override BLOB format buffer should have height == width");
+            } else {
+                LOG_ALWAYS_FATAL_IF(buffer->height != 1,
+                        "BLOB format buffer should have height value 1");
+            }
+
 
             pData = buffer->data;
             dataSize = Image_getJpegSize(buffer, usingRGBAOverride);
diff --git a/media/tests/MediaFrameworkTest/assets/volantis.jpg b/media/tests/MediaFrameworkTest/assets/volantis.jpg
new file mode 100644
index 0000000..cfe300f
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/assets/volantis.jpg
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/res/raw/volantis.jpg b/media/tests/MediaFrameworkTest/res/raw/volantis.jpg
new file mode 100644
index 0000000..cfe300f
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/res/raw/volantis.jpg
Binary files differ
diff --git a/media/tests/MediaFrameworkTest/res/values/exifinterface.xml b/media/tests/MediaFrameworkTest/res/values/exifinterface.xml
index eb13ff37..d556ad3 100644
--- a/media/tests/MediaFrameworkTest/res/values/exifinterface.xml
+++ b/media/tests/MediaFrameworkTest/res/values/exifinterface.xml
@@ -105,4 +105,34 @@
         <item>1</item>
         <item />
     </array>
+    <array name="volantis_jpg">
+        <item>false</item>
+        <item>0</item>
+        <item>0</item>
+        <item>true</item>
+        <item>37.423</item>
+        <item>-122.162</item>
+        <item>0.0</item>
+        <item>htc</item>
+        <item>Nexus 9</item>
+        <item>1.2904</item>
+        <item>2016:03:09 17:36:42</item>
+        <item>0.0083</item>
+        <item>64</item>
+        <item>3097/1000</item>
+        <item />
+        <item />
+        <item>2016:03:09</item>
+        <item>37/1,25/1,2291/100</item>
+        <item>N</item>
+        <item>122/1,9/1,4330/100</item>
+        <item>W</item>
+        <item />
+        <item>08:35:34</item>
+        <item>720</item>
+        <item>1280</item>
+        <item>175</item>
+        <item>1</item>
+        <item>0</item>
+    </array>
 </resources>
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
index cff18cf..5bd6079 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
@@ -51,10 +51,12 @@
     private static final String EXIF_BYTE_ORDER_II_JPEG = "image_exif_byte_order_ii.jpg";
     private static final String EXIF_BYTE_ORDER_MM_JPEG = "image_exif_byte_order_mm.jpg";
     private static final String LG_G4_ISO_800_DNG = "lg_g4_iso_800.dng";
+    private static final String VOLANTIS_JPEG = "volantis.jpg";
     private static final int[] IMAGE_RESOURCES = new int[] {
-            R.raw.image_exif_byte_order_ii,  R.raw.image_exif_byte_order_mm, R.raw.lg_g4_iso_800 };
+            R.raw.image_exif_byte_order_ii,  R.raw.image_exif_byte_order_mm, R.raw.lg_g4_iso_800,
+            R.raw.volantis };
     private static final String[] IMAGE_FILENAMES = new String[] {
-            EXIF_BYTE_ORDER_II_JPEG, EXIF_BYTE_ORDER_MM_JPEG, LG_G4_ISO_800_DNG };
+            EXIF_BYTE_ORDER_II_JPEG, EXIF_BYTE_ORDER_MM_JPEG, LG_G4_ISO_800_DNG, VOLANTIS_JPEG };
 
     private static final String[] EXIF_TAGS = {
             ExifInterface.TAG_MAKE,
@@ -415,7 +417,7 @@
         testExifInterfaceForRaw(LG_G4_ISO_800_DNG, R.array.lg_g4_iso_800_dng);
     }
 
-    public void testCorruptedImage() {
+    public void testCorruptedImage() throws Throwable {
         byte[] bytes = new byte[1024];
         try {
             new ExifInterface(new ByteArrayInputStream(bytes));
@@ -424,4 +426,9 @@
             // Success
         }
     }
+
+    public void testReadExifDataFromVolantisJpg() throws Throwable {
+        // Test if it is possible to parse the volantis generated JPEG smoothly.
+        testExifInterfaceForJpeg(VOLANTIS_JPEG, R.array.volantis_jpg);
+    }
 }
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 637e06e..6fe239e 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -5,6 +5,8 @@
     <uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
     <uses-permission android:name="android.permission.REMOVE_TASKS" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.CACHE_CONTENT" />
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
 
     <application
         android:name=".DocumentsApplication"
@@ -40,18 +42,6 @@
         </activity>
 
         <activity
-            android:name=".DownloadsActivity"
-            android:theme="@style/DocumentsTheme"
-            android:label="@string/downloads_label"
-            android:icon="@drawable/ic_doc_text">
-            <intent-filter>
-                <action android:name="android.provider.action.MANAGE_ROOT" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:mimeType="vnd.android.document/root" />
-            </intent-filter>
-        </activity>
-
-        <activity
             android:name=".LauncherActivity"
             android:theme="@android:style/Theme.NoDisplay"
             android:icon="@drawable/ic_files_app"
@@ -72,6 +62,10 @@
                 <action android:name="android.intent.action.MAIN" />
             </intent-filter>
             <intent-filter>
+                <action android:name="android.intent.action.VIEW_DOWNLOADS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <intent-filter>
                 <action android:name="android.provider.action.BROWSE" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:mimeType="vnd.android.document/root" />
@@ -113,6 +107,12 @@
             </intent-filter>
         </receiver>
 
+        <receiver android:name=".BootReceiver">
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED" />
+            </intent-filter>
+        </receiver>
+
         <service
             android:name=".services.FileOperationService"
             android:exported="false">
diff --git a/packages/DocumentsUI/app-perf-tests/Android.mk b/packages/DocumentsUI/app-perf-tests/Android.mk
new file mode 100644
index 0000000..3f12906
--- /dev/null
+++ b/packages/DocumentsUI/app-perf-tests/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+#LOCAL_SDK_VERSION := current
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+
+LOCAL_JAVA_LIBRARIES := android-support-v4 android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ub-uiautomator
+
+LOCAL_PACKAGE_NAME := DocumentsUIAppPerfTests
+LOCAL_INSTRUMENTATION_FOR := DocumentsUI
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
diff --git a/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml b/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml
new file mode 100644
index 0000000..1c3ed80
--- /dev/null
+++ b/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.documentsui.appperftests">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+
+        <activity
+            android:name="com.android.documentsui.LauncherActivity" />
+    </application>
+
+    <!-- This package instrumentates itself, so the DocumentsUI process can be killed without
+         killing the testing package. -->
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.documentsui.appperftests"
+        android:label="App performance tests for DocumentsUI" />
+
+</manifest>
diff --git a/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java
new file mode 100644
index 0000000..d6e8a96
--- /dev/null
+++ b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 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.documentsui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.provider.DocumentsContract;
+import android.support.test.uiautomator.UiDevice;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+@LargeTest
+public class FilesAppPerfTest extends InstrumentationTestCase {
+
+    // Keys used to report metrics to APCT.
+    private static final String KEY_FILES_COLD_START_PERFORMANCE_MEDIAN =
+            "files-cold-start-performance-median";
+    private static final String KEY_FILES_WARM_START_PERFORMANCE_MEDIAN =
+            "files-warm-start-performance-median";
+
+    private static final String TARGET_PACKAGE = "com.android.documentsui";
+
+    private static final int NUM_MEASUREMENTS = 10;
+
+    private LauncherActivity mActivity;
+    private UiDevice mDevice;
+
+    @Override
+    public void setUp() {
+        mDevice = UiDevice.getInstance(getInstrumentation());
+    }
+
+    public void testFilesColdStartPerformance() throws Exception {
+        runFilesStartPerformanceTest(true);
+    }
+
+    public void testFilesWarmStartPerformance() throws Exception {
+        runFilesStartPerformanceTest(false);
+    }
+
+    public void runFilesStartPerformanceTest(boolean cold) throws Exception {
+        long[] measurements = new long[NUM_MEASUREMENTS];
+        for (int i = 0; i < NUM_MEASUREMENTS; i++) {
+            if (cold) {
+                // Kill all providers, as well as DocumentsUI to measure a cold start.
+                killProviders();
+                mDevice.executeShellCommand("am force-stop " + TARGET_PACKAGE);
+            }
+            mDevice.waitForIdle();
+
+            LauncherActivity.testCaseLatch = new CountDownLatch(1);
+            mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
+                    LauncherActivity.class, null);
+            LauncherActivity.testCaseLatch.await();
+            measurements[i] = LauncherActivity.measurement;
+        }
+
+        reportMetrics(cold ? KEY_FILES_COLD_START_PERFORMANCE_MEDIAN
+                : KEY_FILES_WARM_START_PERFORMANCE_MEDIAN, measurements);
+    }
+
+    private void reportMetrics(String key, long[] measurements) {
+        final Bundle status = new Bundle();
+        Arrays.sort(measurements);
+        final long median = measurements[NUM_MEASUREMENTS / 2 - 1];
+        status.putDouble(key, median);
+
+        getInstrumentation().sendStatus(Activity.RESULT_OK, status);
+    }
+
+    private void killProviders() throws Exception {
+        final PackageManager pm = getInstrumentation().getContext().getPackageManager();
+        final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE);
+        final List<ResolveInfo> providers = pm.queryIntentContentProviders(intent, 0);
+        for (ResolveInfo info : providers) {
+            final String packageName = info.providerInfo.packageName;
+            mDevice.executeShellCommand("am force-stop " + packageName);
+        }
+    }
+}
diff --git a/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/LauncherActivity.java b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/LauncherActivity.java
new file mode 100644
index 0000000..21fc52e
--- /dev/null
+++ b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/LauncherActivity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 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.documentsui;
+
+import static com.android.documentsui.Shared.EXTRA_BENCHMARK;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+
+import java.util.concurrent.CountDownLatch;
+
+public class LauncherActivity extends Activity {
+    private static final String TARGET_PACKAGE = "com.android.documentsui";
+    private static final int BENCHMARK_REQUEST_CODE = 1986;
+
+    public static CountDownLatch testCaseLatch = null;
+    public static long measurement = -1;
+
+    private long mStartTime = -1;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        new Handler().post(new Runnable() {
+            @Override public void run() {
+                final Intent intent = new Intent("android.intent.action.OPEN_DOCUMENT");
+                intent.addCategory(Intent.CATEGORY_OPENABLE);
+                intent.putExtra(EXTRA_BENCHMARK, true);
+                intent.setType("*/*");
+
+                mStartTime = System.currentTimeMillis();
+                startActivityForResult(intent, BENCHMARK_REQUEST_CODE);
+            }
+        });
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == BENCHMARK_REQUEST_CODE) {
+            measurement = System.currentTimeMillis() - mStartTime;
+            testCaseLatch.countDown();
+            finish();
+        }
+    }
+}
diff --git a/packages/DocumentsUI/res/animator-ldrtl/dir_leave.xml b/packages/DocumentsUI/res/animator-ldrtl/dir_leave.xml
deleted file mode 100644
index 8e2925c..0000000
--- a/packages/DocumentsUI/res/animator-ldrtl/dir_leave.xml
+++ /dev/null
@@ -1,22 +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.
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:valueFrom="0"
-    android:valueTo="-1"
-    android:propertyName="position"
-    android:valueType="floatType"
-    android:duration="@android:integer/config_mediumAnimTime"
-    android:interpolator="@android:interpolator/accelerate_quad" />
diff --git a/packages/DocumentsUI/res/animator/dir_enter.xml b/packages/DocumentsUI/res/animator/dir_enter.xml
index 7f547f1..43c50bd 100644
--- a/packages/DocumentsUI/res/animator/dir_enter.xml
+++ b/packages/DocumentsUI/res/animator/dir_enter.xml
@@ -13,10 +13,24 @@
      limitations under the License.
 -->
 
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:valueFrom="1"
-    android:valueTo="0"
-    android:propertyName="position"
-    android:valueType="floatType"
-    android:duration="@android:integer/config_mediumAnimTime"
-    android:interpolator="@android:interpolator/decelerate_quad" />
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:ordering="together">
+
+    <objectAnimator
+        android:valueFrom="0f"
+        android:valueTo="1f"
+        android:propertyName="alpha"
+        android:valueType="floatType"
+        android:duration="@android:integer/config_mediumAnimTime"
+        android:interpolator="@android:interpolator/decelerate_quad" />
+
+    <!-- position property maps to AnimationView.setPosition -->
+    <objectAnimator
+        android:propertyName="position"
+        android:valueFrom="1"
+        android:valueTo="0"
+        android:valueType="floatType"
+        android:duration="@android:integer/config_mediumAnimTime"
+        android:interpolator="@android:interpolator/decelerate_quad" />
+
+</set>
diff --git a/packages/DocumentsUI/res/animator/dir_leave.xml b/packages/DocumentsUI/res/animator/dir_leave.xml
index fda0faf..7574655 100644
--- a/packages/DocumentsUI/res/animator/dir_leave.xml
+++ b/packages/DocumentsUI/res/animator/dir_leave.xml
@@ -13,10 +13,24 @@
      limitations under the License.
 -->
 
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:valueFrom="0"
-    android:valueTo="1"
-    android:propertyName="position"
-    android:valueType="floatType"
-    android:duration="@android:integer/config_mediumAnimTime"
-    android:interpolator="@android:interpolator/accelerate_quad" />
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:ordering="together">
+
+    <objectAnimator
+        android:valueFrom="1f"
+        android:valueTo="0f"
+        android:propertyName="alpha"
+        android:valueType="floatType"
+        android:duration="@android:integer/config_mediumAnimTime"
+        android:interpolator="@android:interpolator/decelerate_quad" />
+
+    <!-- position property maps to AnimationView.setPosition -->
+    <objectAnimator
+        android:valueFrom="0"
+        android:valueTo="1"
+        android:propertyName="position"
+        android:valueType="floatType"
+        android:duration="@android:integer/config_mediumAnimTime"
+        android:interpolator="@android:interpolator/accelerate_quad" />
+
+</set>
\ No newline at end of file
diff --git a/packages/DocumentsUI/res/animator-ldrtl/dir_enter.xml b/packages/DocumentsUI/res/animator/fade_in.xml
similarity index 90%
rename from packages/DocumentsUI/res/animator-ldrtl/dir_enter.xml
rename to packages/DocumentsUI/res/animator/fade_in.xml
index 6c7e224..3ce012b 100644
--- a/packages/DocumentsUI/res/animator-ldrtl/dir_enter.xml
+++ b/packages/DocumentsUI/res/animator/fade_in.xml
@@ -14,9 +14,9 @@
 -->
 
 <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:valueFrom="-1"
-    android:valueTo="0"
-    android:propertyName="position"
+    android:valueFrom="0f"
+    android:valueTo="1f"
+    android:propertyName="alpha"
     android:valueType="floatType"
     android:duration="@android:integer/config_mediumAnimTime"
     android:interpolator="@android:interpolator/decelerate_quad" />
diff --git a/packages/DocumentsUI/res/animator-ldrtl/dir_enter.xml b/packages/DocumentsUI/res/animator/fade_out.xml
similarity index 90%
copy from packages/DocumentsUI/res/animator-ldrtl/dir_enter.xml
copy to packages/DocumentsUI/res/animator/fade_out.xml
index 6c7e224..8d02c77 100644
--- a/packages/DocumentsUI/res/animator-ldrtl/dir_enter.xml
+++ b/packages/DocumentsUI/res/animator/fade_out.xml
@@ -14,9 +14,9 @@
 -->
 
 <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:valueFrom="-1"
-    android:valueTo="0"
-    android:propertyName="position"
+    android:valueFrom="1f"
+    android:valueTo="0f"
+    android:propertyName="alpha"
     android:valueType="floatType"
     android:duration="@android:integer/config_mediumAnimTime"
     android:interpolator="@android:interpolator/decelerate_quad" />
diff --git a/packages/DocumentsUI/res/color/item_details.xml b/packages/DocumentsUI/res/color/item_details.xml
new file mode 100644
index 0000000..769b944
--- /dev/null
+++ b/packages/DocumentsUI/res/color/item_details.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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="true"
+        android:color="?android:attr/textColorPrimary"
+        android:alpha="0.63" />
+    <item
+        android:state_enabled="false"
+        android:color="?android:attr/textColorPrimary"
+        android:alpha="0.3" />
+</selector>
diff --git a/packages/DocumentsUI/res/color/item_title.xml b/packages/DocumentsUI/res/color/item_title.xml
new file mode 100644
index 0000000..ef6aea3
--- /dev/null
+++ b/packages/DocumentsUI/res/color/item_title.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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="true"
+        android:color="?android:attr/textColorPrimary" />
+    <item
+        android:state_enabled="false"
+        android:color="?android:attr/textColorPrimary"
+        android:alpha="0.3" />
+</selector>
diff --git a/packages/DocumentsUI/res/layout/dialog_open_scoped_directory.xml b/packages/DocumentsUI/res/layout/dialog_open_scoped_directory.xml
new file mode 100644
index 0000000..bfb0271
--- /dev/null
+++ b/packages/DocumentsUI/res/layout/dialog_open_scoped_directory.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 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:theme="@style/Theme.AppCompat.Light.Dialog.Alert"
+    android:orientation="vertical"
+    android:paddingEnd="24dp"
+    android:paddingStart="24dp" >
+
+    <TextView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/message"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:paddingEnd="24dp"
+        android:paddingStart="32dp"
+        android:paddingTop="24dp">
+    </TextView>
+
+    <CheckBox
+        android:id="@+id/do_not_ask_checkbox"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dip"
+        android:text="@string/never_ask_again"
+        android:textColor="?android:attr/textColorSecondary"
+        android:visibility="gone" />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/DocumentsUI/res/layout/fragment_directory.xml b/packages/DocumentsUI/res/layout/fragment_directory.xml
index 03c6a83..8eb46dd 100644
--- a/packages/DocumentsUI/res/layout/fragment_directory.xml
+++ b/packages/DocumentsUI/res/layout/fragment_directory.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 
-<com.android.documentsui.DirectoryView xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.documentsui.dirlist.AnimationView
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@color/directory_background"
@@ -99,4 +100,4 @@
 
     </FrameLayout>
 
-</com.android.documentsui.DirectoryView>
+</com.android.documentsui.dirlist.AnimationView>
diff --git a/packages/DocumentsUI/res/layout/item_dir_grid.xml b/packages/DocumentsUI/res/layout/item_dir_grid.xml
index a4f06d1..429a972 100644
--- a/packages/DocumentsUI/res/layout/item_dir_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_dir_grid.xml
@@ -66,7 +66,7 @@
             android:singleLine="true"
             android:textAlignment="viewStart"
             android:textAppearance="@android:style/TextAppearance.Material.Subhead"
-            android:textColor="@*android:color/primary_text_default_material_light" />
+            android:textColor="@color/item_title" />
 
     </LinearLayout>
 
diff --git a/packages/DocumentsUI/res/layout/item_doc_grid.xml b/packages/DocumentsUI/res/layout/item_doc_grid.xml
index af1703f..56a061f 100644
--- a/packages/DocumentsUI/res/layout/item_doc_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_grid.xml
@@ -93,7 +93,7 @@
             android:ellipsize="end"
             android:textAlignment="viewStart"
             android:textAppearance="@android:style/TextAppearance.Material.Subhead"
-            android:textColor="@*android:color/primary_text_default_material_light" />
+            android:textColor="@color/item_title" />
 
         <TextView
             android:id="@+id/size"
@@ -106,7 +106,7 @@
             android:ellipsize="end"
             android:textAlignment="viewStart"
             android:textAppearance="@android:style/TextAppearance.Material.Caption"
-            android:textColor="@*android:color/primary_text_default_material_light" />
+            android:textColor="@color/item_details" />
 
         <TextView
             android:id="@+id/date"
@@ -118,7 +118,7 @@
             android:ellipsize="end"
             android:textAlignment="viewStart"
             android:textAppearance="@android:style/TextAppearance.Material.Caption"
-            android:textColor="@*android:color/primary_text_default_material_light" />
+            android:textColor="@color/item_details" />
 
     </RelativeLayout>
 
diff --git a/packages/DocumentsUI/res/layout/item_doc_list.xml b/packages/DocumentsUI/res/layout/item_doc_list.xml
index 29f65e09..a939fcd 100644
--- a/packages/DocumentsUI/res/layout/item_doc_list.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_list.xml
@@ -85,7 +85,7 @@
                 android:singleLine="true"
                 android:textAlignment="viewStart"
                 android:textAppearance="@android:style/TextAppearance.Material.Subhead"
-                android:textColor="?android:attr/textColorPrimary" />
+                android:textColor="@color/item_title" />
 
             <LinearLayout
                 android:id="@+id/line2"
@@ -102,8 +102,8 @@
                     android:ellipsize="end"
                     android:singleLine="true"
                     android:textAlignment="viewStart"
-                    android:textAppearance="@android:style/TextAppearance.Material.Body1"
-                    android:textColor="?android:attr/textColorSecondary" />
+                    android:textAppearance="@android:style/TextAppearance.Material.Caption"
+                    android:textColor="@color/item_details" />
 
                 <TextView
                     android:id="@+id/size"
@@ -113,8 +113,8 @@
                     android:ellipsize="end"
                     android:singleLine="true"
                     android:textAlignment="viewStart"
-                    android:textAppearance="@android:style/TextAppearance.Material.Body1"
-                    android:textColor="?android:attr/textColorSecondary" />
+                    android:textAppearance="@android:style/TextAppearance.Material.Caption"
+                    android:textColor="@color/item_details" />
 
                 <TextView
                     android:id="@android:id/summary"
@@ -125,8 +125,8 @@
                     android:ellipsize="end"
                     android:singleLine="true"
                     android:textAlignment="viewStart"
-                    android:textAppearance="@android:style/TextAppearance.Material.Body1"
-                    android:textColor="?android:attr/textColorSecondary" />
+                    android:textAppearance="@android:style/TextAppearance.Material.Caption"
+                    android:textColor="@color/item_details" />
             </LinearLayout>
         </LinearLayout>
     </LinearLayout>
diff --git a/packages/DocumentsUI/res/values-af/strings.xml b/packages/DocumentsUI/res/values-af/strings.xml
index f01c81d..17e2c31 100644
--- a/packages/DocumentsUI/res/values-af/strings.xml
+++ b/packages/DocumentsUI/res/values-af/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Hernoem"</string>
     <string name="rename_error" msgid="4203041674883412606">"Kon nie dokument hernoem nie"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sommige lêers is omgeskakel"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Laat toe"</string>
     <string name="deny" msgid="2081879885755434506">"Weier"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">Vee <xliff:g id="COUNT_1">%1$d</xliff:g> lêers uit?</item>
       <item quantity="one">Vee <xliff:g id="COUNT_0">%1$d</xliff:g> lêer uit?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> gekies</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> gekies</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-am/strings.xml b/packages/DocumentsUI/res/values-am/strings.xml
index c61db57..0cb68de 100644
--- a/packages/DocumentsUI/res/values-am/strings.xml
+++ b/packages/DocumentsUI/res/values-am/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"እንደገና ሰይም"</string>
     <string name="rename_error" msgid="4203041674883412606">"ሰነዱን ዳግም መሰየም አልተሳካም"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"አንዳንድ ፋይሎች ተለውጠዋል"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"ይፍቀዱ"</string>
     <string name="deny" msgid="2081879885755434506">"ያስተባብሉ"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-ar/strings.xml b/packages/DocumentsUI/res/values-ar/strings.xml
index 817f226..4a30257 100644
--- a/packages/DocumentsUI/res/values-ar/strings.xml
+++ b/packages/DocumentsUI/res/values-ar/strings.xml
@@ -138,6 +138,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"إعادة تسمية"</string>
     <string name="rename_error" msgid="4203041674883412606">"أخفقت إعادة تسمية المستند."</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"تم تحويل بعض الملفات"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"السماح"</string>
     <string name="deny" msgid="2081879885755434506">"رفض"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
@@ -148,5 +152,12 @@
       <item quantity="other">هل تريد حذف <xliff:g id="COUNT_1">%1$d</xliff:g> ملف؟</item>
       <item quantity="one">هل تريد حذف <xliff:g id="COUNT_0">%1$d</xliff:g> ملف؟</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="zero">تم تحديد <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="two">تم تحديد <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="few">تم تحديد <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="many">تم تحديد <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">تم تحديد <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">تم تحديد <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-az-rAZ/strings.xml b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
index 2e6f04c..b432680 100644
--- a/packages/DocumentsUI/res/values-az-rAZ/strings.xml
+++ b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Adını dəyişdirin"</string>
     <string name="rename_error" msgid="4203041674883412606">"Sənəd adını dəyişmək uğursuz oldu"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bəzi fayllar konvertasiya edilib"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"İcazə verin"</string>
     <string name="deny" msgid="2081879885755434506">"Rədd et"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> fayl silinsin?</item>
       <item quantity="one"> <xliff:g id="COUNT_0">%1$d</xliff:g> fayl silinsin?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> seçilib</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> seçilib</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
index 36e24834..3e36503 100644
--- a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
@@ -117,6 +117,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Preimenuj"</string>
     <string name="rename_error" msgid="4203041674883412606">"Preimenovanje dokumenta nije uspelo"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke datoteke su konvertovane"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Dozvoli"</string>
     <string name="deny" msgid="2081879885755434506">"Odbij"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
@@ -124,5 +128,9 @@
       <item quantity="few">Želite li da izbrišete <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke?</item>
       <item quantity="other">Želite li da izbrišete <xliff:g id="COUNT_1">%1$d</xliff:g> datoteka?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">Izabrana je <xliff:g id="COUNT_1">%1$d</xliff:g> stavka</item>
+      <item quantity="few">Izabrane su <xliff:g id="COUNT_1">%1$d</xliff:g> stavke</item>
+      <item quantity="other">Izabrano je <xliff:g id="COUNT_1">%1$d</xliff:g> stavki</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml
index 74d18f8..a1ac5c9 100644
--- a/packages/DocumentsUI/res/values-bg/strings.xml
+++ b/packages/DocumentsUI/res/values-bg/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Преименуване"</string>
     <string name="rename_error" msgid="4203041674883412606">"Преименуването на документа не бе успешно"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Някои файлове бяха преобразувани"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Разрешаване"</string>
     <string name="deny" msgid="2081879885755434506">"Отказване"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">Искате ли да изтриете <xliff:g id="COUNT_1">%1$d</xliff:g> файла?</item>
       <item quantity="one">Искате ли да изтриете <xliff:g id="COUNT_0">%1$d</xliff:g> файл?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">Избрахте <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Избрахте <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-bn-rBD/strings.xml b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
index 0e3c552..7b88194 100644
--- a/packages/DocumentsUI/res/values-bn-rBD/strings.xml
+++ b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"পুনঃনামকরণ"</string>
     <string name="rename_error" msgid="4203041674883412606">"দস্তাবেজের পুনঃনামকরণ ব্যর্থ হয়েছে৷"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"কিছু ফাইল রূপান্তরিত হয়েছে"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"অনুমতি দিন"</string>
     <string name="deny" msgid="2081879885755434506">"আস্বীকার করুন"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>টি ফাইল মুছবেন?</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টি ফাইল মুছবেন?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>টি নির্বাচন করা হয়েছে</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টি নির্বাচন করা হয়েছে</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-bs-rBA/strings.xml b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
index ea8214e..9daa80a 100644
--- a/packages/DocumentsUI/res/values-bs-rBA/strings.xml
+++ b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
@@ -117,6 +117,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Preimenuj"</string>
     <string name="rename_error" msgid="4203041674883412606">"Nije uspjelo preimenovanje dokumenta"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke od datoteka su pretvorene"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Dozvoli"</string>
     <string name="deny" msgid="2081879885755434506">"Odbijte"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
@@ -124,5 +128,9 @@
       <item quantity="few">Želite li izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> fajla.</item>
       <item quantity="other">Želite li izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> fajlova.</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> stavka je odabrana</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> stavke su odabrane</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> stavki je odabrano</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml
index 8a35368..b7d887e 100644
--- a/packages/DocumentsUI/res/values-ca/strings.xml
+++ b/packages/DocumentsUI/res/values-ca/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Canvia el nom"</string>
     <string name="rename_error" msgid="4203041674883412606">"No s\'ha pogut canviar el nom del document"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"S\'han convertit alguns fitxers"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Permet"</string>
     <string name="deny" msgid="2081879885755434506">"Denega"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">Vols suprimir <xliff:g id="COUNT_1">%1$d</xliff:g> fitxers?</item>
       <item quantity="one">Vols suprimir <xliff:g id="COUNT_0">%1$d</xliff:g> fitxer?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elements seleccionats</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> element seleccionat</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml
index 001a84b..d58615d 100644
--- a/packages/DocumentsUI/res/values-cs/strings.xml
+++ b/packages/DocumentsUI/res/values-cs/strings.xml
@@ -124,6 +124,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Přejmenovat"</string>
     <string name="rename_error" msgid="4203041674883412606">"Dokument se nepodařilo přejmenovat."</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Některé soubory byly převedeny"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Povolit"</string>
     <string name="deny" msgid="2081879885755434506">"Odepřít"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
@@ -132,5 +136,10 @@
       <item quantity="other">Smazat <xliff:g id="COUNT_1">%1$d</xliff:g> souborů?</item>
       <item quantity="one">Smazat <xliff:g id="COUNT_0">%1$d</xliff:g> soubor?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="few">Vybrány <xliff:g id="COUNT_1">%1$d</xliff:g> položky</item>
+      <item quantity="many">Vybráno <xliff:g id="COUNT_1">%1$d</xliff:g> položky</item>
+      <item quantity="other">Vybráno <xliff:g id="COUNT_1">%1$d</xliff:g> položek</item>
+      <item quantity="one">Vybrána <xliff:g id="COUNT_0">%1$d</xliff:g> položka</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-da/strings.xml b/packages/DocumentsUI/res/values-da/strings.xml
index a72cf02..99338f6 100644
--- a/packages/DocumentsUI/res/values-da/strings.xml
+++ b/packages/DocumentsUI/res/values-da/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Omdøb"</string>
     <string name="rename_error" msgid="4203041674883412606">"Dokumentet kunne ikke omdøbes"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Nogle filer er konverteret"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Tillad"</string>
     <string name="deny" msgid="2081879885755434506">"Afvis"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one">Vil du slette <xliff:g id="COUNT_1">%1$d</xliff:g> filer?</item>
       <item quantity="other">Vil du slette <xliff:g id="COUNT_1">%1$d</xliff:g> filer?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">Der er valgt <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Der er valgt <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml
index ed589e0..373b0582 100644
--- a/packages/DocumentsUI/res/values-de/strings.xml
+++ b/packages/DocumentsUI/res/values-de/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Umbenennen"</string>
     <string name="rename_error" msgid="4203041674883412606">"Dokument konnte nicht umbenannt werden"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Einige Dateien wurden konvertiert"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Zulassen"</string>
     <string name="deny" msgid="2081879885755434506">"Ablehnen"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">Möchtest du <xliff:g id="COUNT_1">%1$d</xliff:g> Dateien löschen?</item>
       <item quantity="one">Möchtest du <xliff:g id="COUNT_0">%1$d</xliff:g> Datei löschen?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ausgewählt</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ausgewählt</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-el/strings.xml b/packages/DocumentsUI/res/values-el/strings.xml
index 7a9d597..539a7c6 100644
--- a/packages/DocumentsUI/res/values-el/strings.xml
+++ b/packages/DocumentsUI/res/values-el/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Μετονομασία"</string>
     <string name="rename_error" msgid="4203041674883412606">"Αποτυχία μετονομασίας εγγράφου"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Ορισμένα αρχεία μετατράπηκαν"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Να επιτρέπεται"</string>
     <string name="deny" msgid="2081879885755434506">"Άρνηση"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">Να διαγραφούν <xliff:g id="COUNT_1">%1$d</xliff:g> αρχεία;</item>
       <item quantity="one">Να διαγραφεί <xliff:g id="COUNT_0">%1$d</xliff:g> αρχείο;</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> επιλεγμένα</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> επιλεγμένο</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-en-rAU/strings.xml b/packages/DocumentsUI/res/values-en-rAU/strings.xml
index 8b46660..1693bdb 100644
--- a/packages/DocumentsUI/res/values-en-rAU/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rAU/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"rename"</string>
     <string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Allow"</string>
     <string name="deny" msgid="2081879885755434506">"Deny"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-en-rGB/strings.xml b/packages/DocumentsUI/res/values-en-rGB/strings.xml
index 8b46660..1693bdb 100644
--- a/packages/DocumentsUI/res/values-en-rGB/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rGB/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"rename"</string>
     <string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Allow"</string>
     <string name="deny" msgid="2081879885755434506">"Deny"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-en-rIN/strings.xml b/packages/DocumentsUI/res/values-en-rIN/strings.xml
index 8b46660..1693bdb 100644
--- a/packages/DocumentsUI/res/values-en-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rIN/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"rename"</string>
     <string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Allow"</string>
     <string name="deny" msgid="2081879885755434506">"Deny"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml
index 9d525af..8ad0439 100644
--- a/packages/DocumentsUI/res/values-es-rUS/strings.xml
+++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Cambiar nombre"</string>
     <string name="rename_error" msgid="4203041674883412606">"No se pudo cambiar el nombre del documento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Se convirtieron algunos archivos"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Denegar"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">¿Deseas borrar <xliff:g id="COUNT_1">%1$d</xliff:g> archivos?</item>
       <item quantity="one">¿Deseas borrar <xliff:g id="COUNT_0">%1$d</xliff:g> archivo?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementos seleccionados</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento seleccionado</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml
index 81fc59abb..c3a4648 100644
--- a/packages/DocumentsUI/res/values-es/strings.xml
+++ b/packages/DocumentsUI/res/values-es/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Cambiar nombre"</string>
     <string name="rename_error" msgid="4203041674883412606">"Error al cambiar el nombre del documento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Se han convertido algunos archivos"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Denegar"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-et-rEE/strings.xml b/packages/DocumentsUI/res/values-et-rEE/strings.xml
index 7cf134e..76f1ef7 100644
--- a/packages/DocumentsUI/res/values-et-rEE/strings.xml
+++ b/packages/DocumentsUI/res/values-et-rEE/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Nimeta ümber"</string>
     <string name="rename_error" msgid="4203041674883412606">"Dokumendi ümbernimetamine ebaõnnestus"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Mõned failid teisendati"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Luba"</string>
     <string name="deny" msgid="2081879885755434506">"Keela"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-eu-rES/strings.xml b/packages/DocumentsUI/res/values-eu-rES/strings.xml
index 2576709..ea77657 100644
--- a/packages/DocumentsUI/res/values-eu-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-eu-rES/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Aldatu izena"</string>
     <string name="rename_error" msgid="4203041674883412606">"Ezin izan zaio aldatu izena dokumentuari"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Artxibo batzuk bihurtu dira"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Onartu"</string>
     <string name="deny" msgid="2081879885755434506">"Ukatu"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> fitxategi ezabatu nahi dituzu?</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> fitxategi ezabatu nahi duzu?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> hautatuta</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> hautatuta</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-fa/strings.xml b/packages/DocumentsUI/res/values-fa/strings.xml
index 312f207..4c2a342 100644
--- a/packages/DocumentsUI/res/values-fa/strings.xml
+++ b/packages/DocumentsUI/res/values-fa/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"تغییر نام"</string>
     <string name="rename_error" msgid="4203041674883412606">"نام سند تغییر نکرد"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"بعضی از فایل‌ها تبدیل شدند"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"ارزیابی‌شده"</string>
     <string name="deny" msgid="2081879885755434506">"اجازه ندارد"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> فایل حذف شود؟</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> فایل حذف شود؟</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">‏<xliff:g id="COUNT_1">%1$d</xliff:g> مورد انتخاب شد</item>
+      <item quantity="other">‏<xliff:g id="COUNT_1">%1$d</xliff:g> مورد انتخاب شد</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index 0cb4de2..a586f7c 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Nimeä uudelleen"</string>
     <string name="rename_error" msgid="4203041674883412606">"Dokumentin nimen muuttaminen epäonnistui."</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Joitakin tiedostoja muunnettiin."</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Salli"</string>
     <string name="deny" msgid="2081879885755434506">"Kiellä"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">Poistetaanko <xliff:g id="COUNT_1">%1$d</xliff:g> tiedostoa?</item>
       <item quantity="one">Poistetaanko <xliff:g id="COUNT_0">%1$d</xliff:g> tiedosto?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> valittu</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> valittu</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
index 73f1bda..cb3a123 100644
--- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml
+++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Renommer"</string>
     <string name="rename_error" msgid="4203041674883412606">"Impossible de renommer le document"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Certains fichiers ont été convertis"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Autoriser"</string>
     <string name="deny" msgid="2081879885755434506">"Refuser"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one">Supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichier?</item>
       <item quantity="other">Supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichiers?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml
index b32696f..0cbc141 100644
--- a/packages/DocumentsUI/res/values-fr/strings.xml
+++ b/packages/DocumentsUI/res/values-fr/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Renommer"</string>
     <string name="rename_error" msgid="4203041674883412606">"Échec du changement de nom du document."</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Certains fichiers ont été convertis"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Autoriser"</string>
     <string name="deny" msgid="2081879885755434506">"Refuser"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one">Supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichier ?</item>
       <item quantity="other">Supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichiers ?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-gl-rES/strings.xml b/packages/DocumentsUI/res/values-gl-rES/strings.xml
index d9bf7e3..1f8ecad 100644
--- a/packages/DocumentsUI/res/values-gl-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-gl-rES/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Cambiar nome"</string>
     <string name="rename_error" msgid="4203041674883412606">"Non se puido cambiar o nome do documento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Convertéronse algúns ficheiros"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Rexeitar"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">Queres eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros?</item>
       <item quantity="one">Queres eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">Seleccionáronse <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Seleccionouse <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-gu-rIN/strings.xml b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
index a1aa3d4..7fc21b6 100644
--- a/packages/DocumentsUI/res/values-gu-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"નામ બદલો"</string>
     <string name="rename_error" msgid="4203041674883412606">"દસ્તાવેજનું નામ બદલવામાં નિષ્ફળ થયાં"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"કેટલીક ફાઇલો રૂપાંતરિત કરી હતી"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"મંજૂરી આપો"</string>
     <string name="deny" msgid="2081879885755434506">"નકારો"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલ કાઢી નાખીએ?</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલ કાઢી નાખીએ?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> પસંદ કરી</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> પસંદ કરી</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-hi/strings.xml b/packages/DocumentsUI/res/values-hi/strings.xml
index 489bb98..87dfb5f 100644
--- a/packages/DocumentsUI/res/values-hi/strings.xml
+++ b/packages/DocumentsUI/res/values-hi/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"नाम बदलें"</string>
     <string name="rename_error" msgid="4203041674883412606">"दस्‍तावेज़ का नाम बदलना विफल रहा"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"कुछ फ़ाइलें रूपांतरित हो गई थीं"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"अनुमति दें"</string>
     <string name="deny" msgid="2081879885755434506">"अस्वीकारें"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-hr/strings.xml b/packages/DocumentsUI/res/values-hr/strings.xml
index 51b8673..f86877e6 100644
--- a/packages/DocumentsUI/res/values-hr/strings.xml
+++ b/packages/DocumentsUI/res/values-hr/strings.xml
@@ -117,6 +117,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Promijeni naziv"</string>
     <string name="rename_error" msgid="4203041674883412606">"Naziv dokumenta nije promijenjen"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke su datoteke konvertirane"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Dopusti"</string>
     <string name="deny" msgid="2081879885755434506">"Odbij"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-hu/strings.xml b/packages/DocumentsUI/res/values-hu/strings.xml
index b7e74e0..14662ad 100644
--- a/packages/DocumentsUI/res/values-hu/strings.xml
+++ b/packages/DocumentsUI/res/values-hu/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Átnevezés"</string>
     <string name="rename_error" msgid="4203041674883412606">"Nem sikerült átnevezni a dokumentumot"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Egyes fájlokat konvertált a rendszer"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Engedélyezés"</string>
     <string name="deny" msgid="2081879885755434506">"Elutasítás"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
index c7a14c1..ecd7669 100644
--- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml
+++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Վերանվանել"</string>
     <string name="rename_error" msgid="4203041674883412606">"Չհաջողվեց վերանվանել փաստաթուղթը"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Որոշ ֆայլեր փոխարկվել են"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Թույլատրել"</string>
     <string name="deny" msgid="2081879885755434506">"Մերժել"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one">Ջնջե՞լ <xliff:g id="COUNT_1">%1$d</xliff:g> ֆայլ:</item>
       <item quantity="other">Ջնջե՞լ <xliff:g id="COUNT_1">%1$d</xliff:g> ֆայլ:</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">Ընտրված է՝ <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Ընտրված է՝ <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-in/strings.xml b/packages/DocumentsUI/res/values-in/strings.xml
index 73ed8bc..b27674e 100644
--- a/packages/DocumentsUI/res/values-in/strings.xml
+++ b/packages/DocumentsUI/res/values-in/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Ganti nama"</string>
     <string name="rename_error" msgid="4203041674883412606">"Gagal mengganti nama dokumen"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Beberapa file dikonversi"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Izinkan"</string>
     <string name="deny" msgid="2081879885755434506">"Tolak"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-is-rIS/strings.xml b/packages/DocumentsUI/res/values-is-rIS/strings.xml
index 1b9ff9a..f351cb8 100644
--- a/packages/DocumentsUI/res/values-is-rIS/strings.xml
+++ b/packages/DocumentsUI/res/values-is-rIS/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Endurnefna"</string>
     <string name="rename_error" msgid="4203041674883412606">"Ekki tókst að endurnefna skjalið"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sumum skrám var umbreytt"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Leyfa"</string>
     <string name="deny" msgid="2081879885755434506">"Hafna"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one">Eyða <xliff:g id="COUNT_1">%1$d</xliff:g> skrá?</item>
       <item quantity="other">Eyða <xliff:g id="COUNT_1">%1$d</xliff:g> skrám?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> valið</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> valin</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index c9329ad..3eb14c0 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Rinomina"</string>
     <string name="rename_error" msgid="4203041674883412606">"Ridenominazione documento non riuscita"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alcuni file sono stati convertiti"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Consenti"</string>
     <string name="deny" msgid="2081879885755434506">"Nega"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">Eliminare <xliff:g id="COUNT_1">%1$d</xliff:g> file?</item>
       <item quantity="one">Eliminare <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementi selezionati</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento selezionato</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-iw/strings.xml b/packages/DocumentsUI/res/values-iw/strings.xml
index 7d4cb9e9..3b0aef8 100644
--- a/packages/DocumentsUI/res/values-iw/strings.xml
+++ b/packages/DocumentsUI/res/values-iw/strings.xml
@@ -124,6 +124,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"שנה שם"</string>
     <string name="rename_error" msgid="4203041674883412606">"ניסיון שינוי שם המסמך נכשל"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"קבצים מסוימים הומרו"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"אפשר"</string>
     <string name="deny" msgid="2081879885755434506">"דחה"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml
index a79ecc5..23b7ab6 100644
--- a/packages/DocumentsUI/res/values-ja/strings.xml
+++ b/packages/DocumentsUI/res/values-ja/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"名前を変更"</string>
     <string name="rename_error" msgid="4203041674883412606">"ドキュメントの名前を変更できませんでした"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"一部のファイルが変換されました"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"許可"</string>
     <string name="deny" msgid="2081879885755434506">"拒否"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> 個のファイルを削除しますか?</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> 個のファイルを削除しますか?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> 個を選択中</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> 個を選択中</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ka-rGE/strings.xml b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
index 7824910..fc36bdb 100644
--- a/packages/DocumentsUI/res/values-ka-rGE/strings.xml
+++ b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"გადარქმევა"</string>
     <string name="rename_error" msgid="4203041674883412606">"დოკუმენტის გადარქმევა ვერ მოხერხდა"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ზოგიერთი ფაილი გარდაქმნილია"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"უფლების მიცემა"</string>
     <string name="deny" msgid="2081879885755434506">"აკრძალვა"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">გსურთ <xliff:g id="COUNT_1">%1$d</xliff:g> ფაილის წაშლა?</item>
       <item quantity="one">გსურთ <xliff:g id="COUNT_0">%1$d</xliff:g> ფაილის წაშლა?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">არჩეულია <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">არჩეულია <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
index 5537af7..101392d 100644
--- a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
+++ b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Атын өзгерту"</string>
     <string name="rename_error" msgid="4203041674883412606">"Құжат қайта аталмады"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Кейбір файлдар түрлендірілді"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Рұқсат беру"</string>
     <string name="deny" msgid="2081879885755434506">"Бас тарту"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файлды жою керек пе?</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> файлды жою керек пе?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> таңдалды</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> таңдалды</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml
index 1e1b3f8..2ee35fe 100644
--- a/packages/DocumentsUI/res/values-km-rKH/strings.xml
+++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"ប្ដូរឈ្មោះ"</string>
     <string name="rename_error" msgid="4203041674883412606">"បានបរាជ័យក្នុងការប្តូរឈ្មោះឯកសារ"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ឯកសារមួយចំនួនត្រូវបានបម្លែង"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"អនុញ្ញាត​"</string>
     <string name="deny" msgid="2081879885755434506">"បដិសេធ"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">លុបឯកសារ <xliff:g id="COUNT_1">%1$d</xliff:g> ច្បាប់ឬ?</item>
       <item quantity="one">លុបឯកសារ <xliff:g id="COUNT_0">%1$d</xliff:g> ច្បាប់ឬ?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">បានជ្រើស <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">បានជ្រើស <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-kn-rIN/strings.xml b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
index 83bed30..b74d6a20 100644
--- a/packages/DocumentsUI/res/values-kn-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"ಮರುಹೆಸರಿಸು"</string>
     <string name="rename_error" msgid="4203041674883412606">"ಡಾಕ್ಯುಮೆಂಟ್ ಮರುಹೆಸರಿಸಲು ವಿಫಲವಾಗಿದೆ"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ಕೆಲವು ಫೈಲ್‌ಗಳನ್ನು ಪರಿವರ್ತಿಸಲಾಗಿದೆ"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"ಅನುಮತಿಸು"</string>
     <string name="deny" msgid="2081879885755434506">"ನಿರಾಕರಿಸು"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one"> <xliff:g id="COUNT_1">%1$d</xliff:g> ಫೈಲ್‌ಗಳನ್ನು ಅಳಿಸುವುದೇ?</item>
       <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> ಫೈಲ್‌ಗಳನ್ನು ಅಳಿಸುವುದೇ?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ko/strings.xml b/packages/DocumentsUI/res/values-ko/strings.xml
index e313925..3c2da97 100644
--- a/packages/DocumentsUI/res/values-ko/strings.xml
+++ b/packages/DocumentsUI/res/values-ko/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"이름 바꾸기"</string>
     <string name="rename_error" msgid="4203041674883412606">"문서 이름을 변경하지 못했습니다."</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"일부 파일이 변환되었습니다."</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"허용"</string>
     <string name="deny" msgid="2081879885755434506">"거부"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">파일 <xliff:g id="COUNT_1">%1$d</xliff:g>개를 삭제하시겠습니까?</item>
       <item quantity="one">파일 <xliff:g id="COUNT_0">%1$d</xliff:g>개를 삭제하시겠습니까?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>개 선택됨</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g>개 선택됨</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ky-rKG/strings.xml b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
index 6b8395a..865e717 100644
--- a/packages/DocumentsUI/res/values-ky-rKG/strings.xml
+++ b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Аталышын өзгөртүү"</string>
     <string name="rename_error" msgid="4203041674883412606">"Документтин аталышы өзгөртүлбөй калды"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Айрым файлдардын форматы өзгөртүлдү"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Уруксат берүү"</string>
     <string name="deny" msgid="2081879885755434506">"Жок"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файл жок кылынсынбы?</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> файл жок кылынсынбы?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> тандалды</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> тандалды</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-lo-rLA/strings.xml b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
index 468853b..4f4a375 100644
--- a/packages/DocumentsUI/res/values-lo-rLA/strings.xml
+++ b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"ປ່ຽນຊື່"</string>
     <string name="rename_error" msgid="4203041674883412606">"ປ່ຽນຊື່ເອກະສານບໍ່ສຳເລັດ"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ປ່ຽນແປງບາງໄຟລ໌ແລ້ວ"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"ອະນຸຍາດ"</string>
     <string name="deny" msgid="2081879885755434506">"ປະ​ຕິ​ເສດ"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml
index 91f5948..fa653fc 100644
--- a/packages/DocumentsUI/res/values-lt/strings.xml
+++ b/packages/DocumentsUI/res/values-lt/strings.xml
@@ -124,6 +124,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Pervardyti"</string>
     <string name="rename_error" msgid="4203041674883412606">"Nepavyko pervardyti dokumento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Kai kurie failai buvo konvertuoti"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Leisti"</string>
     <string name="deny" msgid="2081879885755434506">"Atmesti"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
@@ -132,5 +136,10 @@
       <item quantity="many">Ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failo?</item>
       <item quantity="other">Ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failų?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">Pasirinktas <xliff:g id="COUNT_1">%1$d</xliff:g> elementas</item>
+      <item quantity="few">Pasirinkti <xliff:g id="COUNT_1">%1$d</xliff:g> elementai</item>
+      <item quantity="many">Pasirinkta <xliff:g id="COUNT_1">%1$d</xliff:g> elemento</item>
+      <item quantity="other">Pasirinkta <xliff:g id="COUNT_1">%1$d</xliff:g> elementų</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml
index d3154d1..8fd73e4 100644
--- a/packages/DocumentsUI/res/values-lv/strings.xml
+++ b/packages/DocumentsUI/res/values-lv/strings.xml
@@ -117,6 +117,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Pārdēvēt"</string>
     <string name="rename_error" msgid="4203041674883412606">"Neizdevās pārdēvēt dokumentu"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Daži faili tika pārveidoti."</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Atļaut"</string>
     <string name="deny" msgid="2081879885755434506">"Noraidīt"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
@@ -124,5 +128,9 @@
       <item quantity="one">Vai izdzēst <xliff:g id="COUNT_1">%1$d</xliff:g> failu?</item>
       <item quantity="other">Vai izdzēst <xliff:g id="COUNT_1">%1$d</xliff:g> failus?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="zero"><xliff:g id="COUNT_1">%1$d</xliff:g> atlasīti</item>
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> atlasīts</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> atlasīti</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-mk-rMK/strings.xml b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
index f7486f1..12455da 100644
--- a/packages/DocumentsUI/res/values-mk-rMK/strings.xml
+++ b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Преименувај"</string>
     <string name="rename_error" msgid="4203041674883412606">"Не успеа да се преименува документот"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Некои датотеки беа конвертирани"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Дозволи"</string>
     <string name="deny" msgid="2081879885755434506">"Одбиј"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one">Да се избрише <xliff:g id="COUNT_1">%1$d</xliff:g> датотека?</item>
       <item quantity="other">Да се избришат <xliff:g id="COUNT_1">%1$d</xliff:g> датотеки?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> е избрана</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> се избрани</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ml-rIN/strings.xml b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
index e164ad2..0c0420d 100644
--- a/packages/DocumentsUI/res/values-ml-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"പേരുമാറ്റുക"</string>
     <string name="rename_error" msgid="4203041674883412606">"ഡോക്യുമെന്റിന്റെ പേരുമാറ്റുന്നത് പരാജയപ്പെട്ടു"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ചില ഫയലുകൾ പരിവർത്തനം ചെയ്യപ്പെട്ടു"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"അനുവദിക്കുക"</string>
     <string name="deny" msgid="2081879885755434506">"നിരസിക്കുക"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ഫയലുകൾ ഇല്ലാതാക്കണോ?</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ഫയൽ ഇല്ലാതാക്കണോ?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> തിരഞ്ഞെടുത്തു</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> തിരഞ്ഞെടുത്തു</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-mn-rMN/strings.xml b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
index fae1f04..2af8556 100644
--- a/packages/DocumentsUI/res/values-mn-rMN/strings.xml
+++ b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Нэр өөрчлөх"</string>
     <string name="rename_error" msgid="4203041674883412606">"Баримт бичгийн нэрийн өөрчилж чадсангүй"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Зарим файлыг хөрвүүлсэн"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Зөвшөөрөх"</string>
     <string name="deny" msgid="2081879885755434506">"Татгалзах"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> файлыг устгах уу?</item>
       <item quantity="one"> <xliff:g id="COUNT_0">%1$d</xliff:g> файлыг устгах уу?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> сонгосон</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> сонгосон</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-mr-rIN/strings.xml b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
index 0def32f..6256a99 100644
--- a/packages/DocumentsUI/res/values-mr-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"पुनर्नामित करा"</string>
     <string name="rename_error" msgid="4203041674883412606">"दस्तऐवज पुनर्नामित करण्‍यात अयशस्वी झाले"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"काही फायली रूपांतरित केल्या होत्या"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"अनुमती द्या"</string>
     <string name="deny" msgid="2081879885755434506">"नकार द्या"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one"> <xliff:g id="COUNT_1">%1$d</xliff:g> फाईल हटवायची?</item>
       <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> फायली हटवायच्या?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> निवडला</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> निवडले</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
index ef62ec4..df896a2 100644
--- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml
+++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Namakan semula"</string>
     <string name="rename_error" msgid="4203041674883412606">"Gagal menamakan semula dokumen"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sesetengah fail telah ditukarkan"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Benarkan"</string>
     <string name="deny" msgid="2081879885755434506">"Nafi"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">Padamkan <xliff:g id="COUNT_1">%1$d</xliff:g> fail?</item>
       <item quantity="one">Padamkan <xliff:g id="COUNT_0">%1$d</xliff:g> fail?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dipilih</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dipilih</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-my-rMM/strings.xml b/packages/DocumentsUI/res/values-my-rMM/strings.xml
index 08bdfc1..14193b2 100644
--- a/packages/DocumentsUI/res/values-my-rMM/strings.xml
+++ b/packages/DocumentsUI/res/values-my-rMM/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"အမည်ပြောင်းရန်"</string>
     <string name="rename_error" msgid="4203041674883412606">"စာရွက်စာတမ်းကို အမည်ပြောင်းခြင်း မအောင်မြင်ပါ"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"အချို့ဖိုင်များကို ပြောင်းလဲထားသည်"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"ခွင့်ပြုသည်"</string>
     <string name="deny" msgid="2081879885755434506">"ငြင်းပယ်သည်"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">ဖိုင် <xliff:g id="COUNT_1">%1$d</xliff:g> ခုကိုဖျက်မလား။</item>
       <item quantity="one">ဖိုင် <xliff:g id="COUNT_0">%1$d</xliff:g> ခုကိုဖျက်မလား။</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ခုရွေးချယ်ထားသည်</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ခုရွေးချယ်ထားသည်</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml
index 3326a55..7d37078 100644
--- a/packages/DocumentsUI/res/values-nb/strings.xml
+++ b/packages/DocumentsUI/res/values-nb/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Gi nytt navn"</string>
     <string name="rename_error" msgid="4203041674883412606">"Kunne ikke gi dokumentet nytt navn"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Noen filer er konvertert"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Tillat"</string>
     <string name="deny" msgid="2081879885755434506">"Avslå"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">Vil du slette <xliff:g id="COUNT_1">%1$d</xliff:g> filer?</item>
       <item quantity="one">Vil du slette <xliff:g id="COUNT_0">%1$d</xliff:g> fil?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> er valgt</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> er valgt</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ne-rNP/strings.xml b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
index 191574c..5a06cd2 100644
--- a/packages/DocumentsUI/res/values-ne-rNP/strings.xml
+++ b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"पुन: नामाकरण गर्नुहोस्"</string>
     <string name="rename_error" msgid="4203041674883412606">"कागजात पुन: नामाकरण गर्न असफल भयो"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"केही फाइलहरू परिवर्तन गरिएका थिए"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"अनुमति दिनुहोस्"</string>
     <string name="deny" msgid="2081879885755434506">"अस्वीकार गर्नुहोस्"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> फाइलहरूलाई मेट्ने हो?</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> फाइललाई मेट्ने हो?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> लाई चयन गरियो</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> लाई चयन गरियो</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-nl/strings.xml b/packages/DocumentsUI/res/values-nl/strings.xml
index ebddf54..0e022af 100644
--- a/packages/DocumentsUI/res/values-nl/strings.xml
+++ b/packages/DocumentsUI/res/values-nl/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Naam wijzigen"</string>
     <string name="rename_error" msgid="4203041674883412606">"Kan naam van document niet wijzigen"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sommige bestanden zijn geconverteerd"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Toestaan"</string>
     <string name="deny" msgid="2081879885755434506">"Weigeren"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-pa-rIN/strings.xml b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
index a8c65e7..4cfe638 100644
--- a/packages/DocumentsUI/res/values-pa-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"ਮੁੜ-ਨਾਮਕਰਨ ਕਰੋ"</string>
     <string name="rename_error" msgid="4203041674883412606">"ਦਸਤਾਵੇਜ਼ ਦਾ ਮੁੜ-ਨਾਮਕਰਨ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ਕੁਝ ਫ਼ਾਈਲਾਂ ਤਬਦੀਲ ਕੀਤੀਆਂ ਗਈਆਂ ਸਨ"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"ਆਗਿਆ ਦਿਓ"</string>
     <string name="deny" msgid="2081879885755434506">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index 60dbda8..b10d8a2 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -124,6 +124,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Zmień nazwę"</string>
     <string name="rename_error" msgid="4203041674883412606">"Nie udało się zmienić nazwy dokumentu"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Niektóre pliki zostały przekonwertowane"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Zezwól"</string>
     <string name="deny" msgid="2081879885755434506">"Odmów"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
@@ -132,5 +136,10 @@
       <item quantity="other">Usunąć <xliff:g id="COUNT_1">%1$d</xliff:g> pliku?</item>
       <item quantity="one">Usunąć <xliff:g id="COUNT_0">%1$d</xliff:g> plik?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="few">Wybrano <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="many">Wybrano <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Wybrano <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Wybrano <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-pt-rBR/strings.xml b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
index 92939ba1..26ec421 100644
--- a/packages/DocumentsUI/res/values-pt-rBR/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Renomear"</string>
     <string name="rename_error" msgid="4203041674883412606">"Falha ao renomear documento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Negar"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one">Excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
       <item quantity="other">Excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-pt-rPT/strings.xml b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
index 2c74e67..490c4d7 100644
--- a/packages/DocumentsUI/res/values-pt-rPT/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Mudar o nome"</string>
     <string name="rename_error" msgid="4203041674883412606">"Falha ao mudar o nome do documento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns ficheiros foram convertidos"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Recusar"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml
index 92939ba1..26ec421 100644
--- a/packages/DocumentsUI/res/values-pt/strings.xml
+++ b/packages/DocumentsUI/res/values-pt/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Renomear"</string>
     <string name="rename_error" msgid="4203041674883412606">"Falha ao renomear documento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Permitir"</string>
     <string name="deny" msgid="2081879885755434506">"Negar"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one">Excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
       <item quantity="other">Excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml
index eda2eac..ef34f3a 100644
--- a/packages/DocumentsUI/res/values-ro/strings.xml
+++ b/packages/DocumentsUI/res/values-ro/strings.xml
@@ -117,6 +117,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Redenumiți"</string>
     <string name="rename_error" msgid="4203041674883412606">"Documentul nu a putut fi redenumit"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Unele fișiere au fost convertite"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Permiteți"</string>
     <string name="deny" msgid="2081879885755434506">"Refuzați"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
@@ -124,5 +128,9 @@
       <item quantity="other">Ștergeți <xliff:g id="COUNT_1">%1$d</xliff:g> de fișiere?</item>
       <item quantity="one">Ștergeți <xliff:g id="COUNT_0">%1$d</xliff:g> fișier?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> selectate</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selectate</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selectat</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml
index 5719fe8..b94b2a5 100644
--- a/packages/DocumentsUI/res/values-ru/strings.xml
+++ b/packages/DocumentsUI/res/values-ru/strings.xml
@@ -124,6 +124,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Переименовать"</string>
     <string name="rename_error" msgid="4203041674883412606">"Не удалось переименовать документ"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Формат некоторых файлов изменен"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Разрешить"</string>
     <string name="deny" msgid="2081879885755434506">"Отклонить"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
@@ -132,5 +136,10 @@
       <item quantity="many">Удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файлов?</item>
       <item quantity="other">Удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файла?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="few">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="many">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-si-rLK/strings.xml b/packages/DocumentsUI/res/values-si-rLK/strings.xml
index 7c2e3a2..a0d764e 100644
--- a/packages/DocumentsUI/res/values-si-rLK/strings.xml
+++ b/packages/DocumentsUI/res/values-si-rLK/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"යළි නම් කරන්න"</string>
     <string name="rename_error" msgid="4203041674883412606">"ලේඛනය යළි නම් කිරීම අසාර්ථක විය"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"සමහර ගොනු පරිවර්තනය කරන ලදී"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"අවසර දෙන්න"</string>
     <string name="deny" msgid="2081879885755434506">"ප්‍රතික්ෂේප කරන්න"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one">ගොනු <xliff:g id="COUNT_1">%1$d</xliff:g>ක් මකන්නද?</item>
       <item quantity="other">ගොනු <xliff:g id="COUNT_1">%1$d</xliff:g>ක් මකන්නද?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>ක් තෝරන ලදී</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>ක් තෝරන ලදී</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sk/strings.xml b/packages/DocumentsUI/res/values-sk/strings.xml
index 818c276..06b7a10 100644
--- a/packages/DocumentsUI/res/values-sk/strings.xml
+++ b/packages/DocumentsUI/res/values-sk/strings.xml
@@ -124,6 +124,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Premenovať"</string>
     <string name="rename_error" msgid="4203041674883412606">"Premenovanie dokumentu zlyhalo"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Niektoré súbory boli konvertované"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Povoliť"</string>
     <string name="deny" msgid="2081879885755434506">"Zamietnuť"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
@@ -132,5 +136,10 @@
       <item quantity="other">Odstrániť <xliff:g id="COUNT_1">%1$d</xliff:g> súborov?</item>
       <item quantity="one">Odstrániť <xliff:g id="COUNT_0">%1$d</xliff:g> súbor?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="few">Vybraté: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="many">Vybraté: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="other">Vybraté: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Vybraté: <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sl/strings.xml b/packages/DocumentsUI/res/values-sl/strings.xml
index 1994f07..ee7bdc9 100644
--- a/packages/DocumentsUI/res/values-sl/strings.xml
+++ b/packages/DocumentsUI/res/values-sl/strings.xml
@@ -124,6 +124,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Preimenuj"</string>
     <string name="rename_error" msgid="4203041674883412606">"Dokumenta ni bilo mogoče preimenovati"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Nekatere datoteke so bile pretvorjene"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Dovoli"</string>
     <string name="deny" msgid="2081879885755434506">"Zavrni"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
@@ -132,5 +136,10 @@
       <item quantity="few">Želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke?</item>
       <item quantity="other">Želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> datotek?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> izbran</item>
+      <item quantity="two"><xliff:g id="COUNT_1">%1$d</xliff:g> izbrana</item>
+      <item quantity="few"><xliff:g id="COUNT_1">%1$d</xliff:g> izbrani</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> izbranih</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sq-rAL/strings.xml b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
index 671b5ea..352da58 100644
--- a/packages/DocumentsUI/res/values-sq-rAL/strings.xml
+++ b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Riemërto"</string>
     <string name="rename_error" msgid="4203041674883412606">"Riemërtimi i dokumentit dështoi"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Disa skedarë u konvertuan"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Lejo"</string>
     <string name="deny" msgid="2081879885755434506">"Moho"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">Të fshihen <xliff:g id="COUNT_1">%1$d</xliff:g> skedarë?</item>
       <item quantity="one">Të fshihet <xliff:g id="COUNT_0">%1$d</xliff:g> skedar?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> të zgjedhur</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> i zgjedhur</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml
index de45e61..0ba3da1 100644
--- a/packages/DocumentsUI/res/values-sr/strings.xml
+++ b/packages/DocumentsUI/res/values-sr/strings.xml
@@ -117,6 +117,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Преименуј"</string>
     <string name="rename_error" msgid="4203041674883412606">"Преименовање документа није успело"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Неке датотеке су конвертоване"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Дозволи"</string>
     <string name="deny" msgid="2081879885755434506">"Одбиј"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
@@ -124,5 +128,9 @@
       <item quantity="few">Желите ли да избришете <xliff:g id="COUNT_1">%1$d</xliff:g> датотеке?</item>
       <item quantity="other">Желите ли да избришете <xliff:g id="COUNT_1">%1$d</xliff:g> датотека?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one">Изабрана је <xliff:g id="COUNT_1">%1$d</xliff:g> ставка</item>
+      <item quantity="few">Изабране су <xliff:g id="COUNT_1">%1$d</xliff:g> ставке</item>
+      <item quantity="other">Изабрано је <xliff:g id="COUNT_1">%1$d</xliff:g> ставки</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sv/strings.xml b/packages/DocumentsUI/res/values-sv/strings.xml
index 7fd4be0..081c331 100644
--- a/packages/DocumentsUI/res/values-sv/strings.xml
+++ b/packages/DocumentsUI/res/values-sv/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Byt namn"</string>
     <string name="rename_error" msgid="4203041674883412606">"Det gick inte att byta namn på dokumentet"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Vissa filer konverterades"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Tillåt"</string>
     <string name="deny" msgid="2081879885755434506">"Neka"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-sw/strings.xml b/packages/DocumentsUI/res/values-sw/strings.xml
index ce042f0..fc4d555 100644
--- a/packages/DocumentsUI/res/values-sw/strings.xml
+++ b/packages/DocumentsUI/res/values-sw/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Badilisha jina"</string>
     <string name="rename_error" msgid="4203041674883412606">"Imeshindwa kubadilisha jina la hati"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Baadhi ya faili zimebadilishwa muundo"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Ruhusu"</string>
     <string name="deny" msgid="2081879885755434506">"Kataza"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">Ungependa kufuta faili <xliff:g id="COUNT_1">%1$d</xliff:g>?</item>
       <item quantity="one">Ungependa kufuta faili <xliff:g id="COUNT_0">%1$d</xliff:g>?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">Imechagua <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Imechagua <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-sw720dp-land/config.xml b/packages/DocumentsUI/res/values-sw720dp-land/config.xml
index 8d9526d..6893d7a 100644
--- a/packages/DocumentsUI/res/values-sw720dp-land/config.xml
+++ b/packages/DocumentsUI/res/values-sw720dp-land/config.xml
@@ -15,5 +15,4 @@
 -->
 
 <resources>
-    <bool name="always_show_summary">true</bool>
 </resources>
diff --git a/packages/DocumentsUI/res/values-ta-rIN/strings.xml b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
index 5bd71ae..30bdc9d 100644
--- a/packages/DocumentsUI/res/values-ta-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"மறுபெயரிடு"</string>
     <string name="rename_error" msgid="4203041674883412606">"ஆவணத்திற்கு மறுபெயரிடுவதில் தோல்வி"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"சில கோப்புகள் மாற்றப்பட்டன"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"அனுமதி"</string>
     <string name="deny" msgid="2081879885755434506">"நிராகரி"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> கோப்புகளை நீக்கவா?</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> கோப்பை நீக்கவா?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> தேர்ந்தெடுக்கப்பட்டன</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> தேர்ந்தெடுக்கப்பட்டது</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-te-rIN/strings.xml b/packages/DocumentsUI/res/values-te-rIN/strings.xml
index 0043ddc..c11840a 100644
--- a/packages/DocumentsUI/res/values-te-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-te-rIN/strings.xml
@@ -110,6 +110,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"పేరు మార్చు"</string>
     <string name="rename_error" msgid="4203041674883412606">"పత్రం పేరు మార్చడంలో విఫలమైంది"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"కొన్ని పైల్‌లు మార్చబడ్డాయి"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"అనుమతించండి"</string>
     <string name="deny" msgid="2081879885755434506">"తిరస్కరించండి"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml
index fbc170e..aba869c 100644
--- a/packages/DocumentsUI/res/values-th/strings.xml
+++ b/packages/DocumentsUI/res/values-th/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"เปลี่ยนชื่อ"</string>
     <string name="rename_error" msgid="4203041674883412606">"ไม่สามารถเปลี่ยนชื่อเอกสาร"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"แปลงบางไฟล์แล้ว"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"อนุญาต"</string>
     <string name="deny" msgid="2081879885755434506">"ปฏิเสธ"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">ลบ <xliff:g id="COUNT_1">%1$d</xliff:g> ไฟล์ใช่ไหม</item>
       <item quantity="one">ลบ <xliff:g id="COUNT_0">%1$d</xliff:g> ไฟล์ใช่ไหม</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">เลือกไว้ <xliff:g id="COUNT_1">%1$d</xliff:g> รายการ</item>
+      <item quantity="one">เลือกไว้ <xliff:g id="COUNT_0">%1$d</xliff:g> รายการ</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-tl/strings.xml b/packages/DocumentsUI/res/values-tl/strings.xml
index 8a4f148..a76a306 100644
--- a/packages/DocumentsUI/res/values-tl/strings.xml
+++ b/packages/DocumentsUI/res/values-tl/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Palitan ang pangalan"</string>
     <string name="rename_error" msgid="4203041674883412606">"Hindi napalitan ang pangalan ng dokumento"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Na-convert ang ilang file"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Payagan"</string>
     <string name="deny" msgid="2081879885755434506">"Tanggihan"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one">Gusto mo bang i-delete ang <xliff:g id="COUNT_1">%1$d</xliff:g> file?</item>
       <item quantity="other">Gusto mo bang i-delete ang <xliff:g id="COUNT_1">%1$d</xliff:g> na file?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ang napili</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ang napili</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml
index ceb5c48..f5e6258 100644
--- a/packages/DocumentsUI/res/values-tr/strings.xml
+++ b/packages/DocumentsUI/res/values-tr/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Yeniden Adlandır"</string>
     <string name="rename_error" msgid="4203041674883412606">"Dokümanın adı değiştirilemedi"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bazı dosyalar dönüştürüldü"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"İzin Ver"</string>
     <string name="deny" msgid="2081879885755434506">"Reddet"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dosya silinsin mi?</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dosya silinsin mi?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> öğe seçildi</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> öğe seçildi</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml
index d5a1fcd..9c4b054 100644
--- a/packages/DocumentsUI/res/values-uk/strings.xml
+++ b/packages/DocumentsUI/res/values-uk/strings.xml
@@ -124,6 +124,10 @@
     <string name="menu_rename" msgid="7678802479104285353">"Перейменувати"</string>
     <string name="rename_error" msgid="4203041674883412606">"Не вдалося перейменувати документ"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Деякі файли конвертовано"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Дозвол."</string>
     <string name="deny" msgid="2081879885755434506">"Забор."</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
diff --git a/packages/DocumentsUI/res/values-ur-rPK/strings.xml b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
index b96a96f..2d4804c 100644
--- a/packages/DocumentsUI/res/values-ur-rPK/strings.xml
+++ b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"نام تبدیل کریں"</string>
     <string name="rename_error" msgid="4203041674883412606">"دستاویز کا نام تبدیل کرنے میں ناکام"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"کچھ فائلوں کو تبدیل کیا گیا تھا"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"اجازت دیں"</string>
     <string name="deny" msgid="2081879885755434506">"مسترد کریں"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> فائلیں حذف کریں؟</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> فائل حذف کریں؟</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> منتخب کردہ</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> منتخب کردہ</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
index 72cc7d9..0a09921 100644
--- a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
+++ b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Qayta nomlash"</string>
     <string name="rename_error" msgid="4203041674883412606">"Hujjatni qayta nomlab bo‘lmadi"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bir nechta fayllar o‘girildi"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Ruxsat berish"</string>
     <string name="deny" msgid="2081879885755434506">"Rad qilish"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ta fayl o‘chirilsinmi?</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta fayl o‘chirilsinmi?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ta belgilandi</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta belgilandi</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-vi/strings.xml b/packages/DocumentsUI/res/values-vi/strings.xml
index adb3ffe..9aca29f 100644
--- a/packages/DocumentsUI/res/values-vi/strings.xml
+++ b/packages/DocumentsUI/res/values-vi/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Đổi tên"</string>
     <string name="rename_error" msgid="4203041674883412606">"Không đổi được tên tài liệu"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Đã chuyển đổi một số tệp"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Cho phép"</string>
     <string name="deny" msgid="2081879885755434506">"Từ chối"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">Xóa <xliff:g id="COUNT_1">%1$d</xliff:g> tệp?</item>
       <item quantity="one">Xóa <xliff:g id="COUNT_0">%1$d</xliff:g> tệp?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">Đã chọn <xliff:g id="COUNT_1">%1$d</xliff:g></item>
+      <item quantity="one">Đã chọn <xliff:g id="COUNT_0">%1$d</xliff:g></item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
index ccf5d42..75dcfbc 100644
--- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"重命名"</string>
     <string name="rename_error" msgid="4203041674883412606">"无法重命名文档"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分文件已转换成其他格式"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"允许"</string>
     <string name="deny" msgid="2081879885755434506">"拒绝"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">删除 <xliff:g id="COUNT_1">%1$d</xliff:g> 个文件?</item>
       <item quantity="one">删除 <xliff:g id="COUNT_0">%1$d</xliff:g> 个文件?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">已选择 <xliff:g id="COUNT_1">%1$d</xliff:g> 项</item>
+      <item quantity="one">已选择 <xliff:g id="COUNT_0">%1$d</xliff:g> 项</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
index ecd0071..b834a11 100644
--- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"重新命名"</string>
     <string name="rename_error" msgid="4203041674883412606">"無法重新命名文件"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分檔案已轉換成其他格式"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"允許"</string>
     <string name="deny" msgid="2081879885755434506">"拒絕"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">要刪除 <xliff:g id="COUNT_1">%1$d</xliff:g> 個檔案嗎?</item>
       <item quantity="one">要刪除 <xliff:g id="COUNT_0">%1$d</xliff:g> 個檔案嗎?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">已選取 <xliff:g id="COUNT_1">%1$d</xliff:g> 個項目</item>
+      <item quantity="one">已選取 <xliff:g id="COUNT_0">%1$d</xliff:g> 個項目</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
index ea83ab2..d6e270a 100644
--- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"重新命名"</string>
     <string name="rename_error" msgid="4203041674883412606">"無法重新命名文件"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分檔案已轉換成其他格式"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"允許"</string>
     <string name="deny" msgid="2081879885755434506">"拒絕"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="other">要刪除 <xliff:g id="COUNT_1">%1$d</xliff:g> 個檔案嗎?</item>
       <item quantity="one">要刪除 <xliff:g id="COUNT_0">%1$d</xliff:g> 個檔案嗎?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="other">已選取 <xliff:g id="COUNT_1">%1$d</xliff:g> 個項目</item>
+      <item quantity="one">已選取 <xliff:g id="COUNT_0">%1$d</xliff:g> 個項目</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values-zu/strings.xml b/packages/DocumentsUI/res/values-zu/strings.xml
index 4588b12..35864a7 100644
--- a/packages/DocumentsUI/res/values-zu/strings.xml
+++ b/packages/DocumentsUI/res/values-zu/strings.xml
@@ -110,11 +110,18 @@
     <string name="menu_rename" msgid="7678802479104285353">"Qamba kabusha"</string>
     <string name="rename_error" msgid="4203041674883412606">"Yehlulekile ukuqamba kabusha idokhumenti"</string>
     <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Amanye amafayela aguqulelwe"</string>
+    <!-- no translation found for open_external_dialog_request (5789329484285817629) -->
+    <skip />
+    <!-- no translation found for never_ask_again (4295278542972859268) -->
+    <skip />
     <string name="allow" msgid="7225948811296386551">"Vumela"</string>
     <string name="deny" msgid="2081879885755434506">"Yala"</string>
     <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772">
       <item quantity="one">Sula amafayela angu-<xliff:g id="COUNT_1">%1$d</xliff:g>?</item>
       <item quantity="other">Sula amafayela angu-<xliff:g id="COUNT_1">%1$d</xliff:g>?</item>
     </plurals>
-    <!-- no translation found for elements_selected (1376955402452875047) -->
+    <plurals name="elements_selected" formatted="false" msgid="1376955402452875047">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> okukhethiwe</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> okukhethiwe</item>
+    </plurals>
 </resources>
diff --git a/packages/DocumentsUI/res/values/colors.xml b/packages/DocumentsUI/res/values/colors.xml
index 3785adf..04b7fee 100644
--- a/packages/DocumentsUI/res/values/colors.xml
+++ b/packages/DocumentsUI/res/values/colors.xml
@@ -23,8 +23,6 @@
     <color name="window_background">#fff1f1f1</color>
     <color name="drawer_background">#fff1f1f1</color>
     <color name="directory_background">#fff7f7f7</color>
-    <color name="item_doc_background">#fffafafa</color>
-    <color name="item_doc_background_selected">#ffe0f2f1</color>
     <color name="menu_search_background">#ff676f74</color>
 
     <color name="primary_dark">@*android:color/primary_dark_material_dark</color>
@@ -35,4 +33,11 @@
 
     <color name="band_select_background">#88ffffff</color>
     <color name="band_select_border">#44000000</color>
+
+    <color name="item_doc_background_disabled">#fff4f4f4</color>
+
+    <!-- TODO: Would be nice to move this to a color-set, but not sure how to support animation -->
+    <color name="item_doc_background">#fffafafa</color>
+    <color name="item_doc_background_selected">#ffe0f2f1</color>
+
 </resources>
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index 8a76540..86087c3 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -21,5 +21,4 @@
     <!-- Intentionally unset. Vendors should set this in an overlay. -->
     <string name="trusted_quick_viewer_package" translatable="false"></string>
     <bool name="list_divider_inset_left">true</bool>
-    <bool name="always_show_summary">false</bool>
 </resources>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index e2d1870..e7406e68 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -200,10 +200,12 @@
          during a copy. [CHAR LIMIT=48] -->
     <string name="notification_copy_files_converted_title">Some files were converted</string>
 
-    <!--  DO NOT TRANSLATE - final phrase has not been decided yet (b/26750152) -->
+    <!-- Text in an alert dialog asking user to grant app access to a given directory in an external storage volume -->
     <string name="open_external_dialog_request">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g>
-        access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> folder on
+        access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> directory on
         <xliff:g id="storage" example="SD Card"><i>^3</i></xliff:g>?</string>
+    <!-- Checkbox that allows user to not be questioned about the directory access request again -->
+    <string name="never_ask_again">Don\'t ask again</string>
     <!-- Text in the button asking user to allow access to a given directory. -->
     <string name="allow">Allow</string>
     <!-- Text in the button asking user to deny access to a given directory. -->
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index 21bdfd9..a548d89 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -46,8 +46,4 @@
         <item name="android:maxHeight">3dp</item>    
     </style>
 
-    <!--  TODO: use the proper dialog and/or inline if not overriding -->
-    <style name="AlertDialogTheme" parent="@style/Theme.AppCompat.Light.Dialog.Alert">
-    </style>
-
 </resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index c9d18b3..fe61094 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -17,11 +17,8 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.Shared.EXTRA_BENCHMARK;
 import static com.android.documentsui.State.MODE_GRID;
-import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_ENTER;
-import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_LEAVE;
-import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
-import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_SIDE;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -34,6 +31,9 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.MessageQueue;
+import android.os.MessageQueue.IdleHandler;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Root;
 import android.support.annotation.CallSuper;
@@ -48,6 +48,7 @@
 
 import com.android.documentsui.SearchViewManager.SearchManagerListener;
 import com.android.documentsui.State.ViewMode;
+import com.android.documentsui.dirlist.AnimationView;
 import com.android.documentsui.dirlist.DirectoryFragment;
 import com.android.documentsui.dirlist.Model;
 import com.android.documentsui.model.DocumentInfo;
@@ -63,6 +64,8 @@
 public abstract class BaseActivity extends Activity
         implements SearchManagerListener, NavigationView.Environment {
 
+    private static final String BENCHMARK_TESTING_PACKAGE = "com.android.documentsui.appperftests";
+
     State mState;
     RootsCache mRoots;
     SearchViewManager mSearchManager;
@@ -95,11 +98,20 @@
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
+        final Intent intent = getIntent();
+
+        // If startup benchmark is requested by a whitelisted testing package, then close the
+        // activity once idle, and notify the testing activity.
+        if (intent.getBooleanExtra(EXTRA_BENCHMARK, false) &&
+                BENCHMARK_TESTING_PACKAGE.equals(getCallingPackage())) {
+            closeOnIdleForTesting();
+        }
+
         setContentView(mLayoutId);
 
         mDrawer = DrawerController.create(this);
         mState = getState(icicle);
-        Metrics.logActivityLaunch(this, mState, getIntent());
+        Metrics.logActivityLaunch(this, mState, intent);
 
         mRoots = DocumentsApplication.getRootsCache(this);
 
@@ -225,7 +237,7 @@
         // Otherwise we delegate loading data from disk to a task
         // to ensure a responsive ui.
         if (mRoots.isRecentsRoot(root)) {
-            refreshCurrentRootAndDirectory(ANIM_NONE);
+            refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE);
         } else {
             new PickRootTask(this, root).executeOnExecutor(getExecutorForCurrentDirectory());
         }
@@ -327,7 +339,7 @@
         // previous directory. Especially after opening a root document, pressing
         // back, wouldn't go to the previous root, but close the activity.
         final int anim = (mState.hasLocationChanged() && mState.stack.size() > 1)
-                ? ANIM_ENTER : ANIM_NONE;
+                ? AnimationView.ANIM_ENTER : AnimationView.ANIM_NONE;
         refreshCurrentRootAndDirectory(anim);
     }
 
@@ -543,7 +555,7 @@
             // Update the restored stack to ensure we have freshest data
             stack.updateDocuments(getContentResolver());
             mState.setStack(stack);
-            refreshCurrentRootAndDirectory(ANIM_SIDE);
+            refreshCurrentRootAndDirectory(AnimationView.ANIM_SIDE);
 
         } catch (FileNotFoundException e) {
             Log.w(mTag, "Failed to restore stack: " + e);
@@ -644,7 +656,7 @@
     private boolean popDir() {
         if (mState.stack.size() > 1) {
             mState.stack.pop();
-            refreshCurrentRootAndDirectory(ANIM_LEAVE);
+            refreshCurrentRootAndDirectory(AnimationView.ANIM_LEAVE);
             return true;
         }
         return false;
@@ -671,9 +683,36 @@
         }
     }
 
+    /**
+     * Closes the activity when it's idle. Used only for tests.
+     */
+    private void closeOnIdleForTesting() {
+        addEventListener(new EventListener() {
+            @Override
+            public void onDirectoryNavigated(Uri uri) {
+            }
+
+            @Override
+            public void onDirectoryLoaded(Uri uri) {
+                getMainLooper().getQueue().addIdleHandler(new IdleHandler() {
+                    @Override
+                    public boolean queueIdle() {
+                        setResult(RESULT_OK);
+                        finish();
+                        return false;
+                    }
+                });
+                new Handler().post(new Runnable() {
+                    @Override public void run() {
+                    }
+                });
+            }
+        });
+    }
+
     private static final class HandleRootsChangedTask
             extends PairedTask<BaseActivity, RootInfo, RootInfo> {
-        DocumentInfo mHome;
+        DocumentInfo mDownloadsDocument;
 
         public HandleRootsChangedTask(BaseActivity activity) {
             super(activity);
@@ -685,28 +724,28 @@
 
             final RootInfo currentRoot = roots[0];
             final Collection<RootInfo> cachedRoots = mOwner.mRoots.getRootsBlocking();
-            RootInfo homeRoot = null;
+            RootInfo downloadsRoot = null;
             for (final RootInfo root : cachedRoots) {
-                if (root.isHome()) {
-                    homeRoot = root;
+                if (root.isDownloads()) {
+                    downloadsRoot = root;
                 }
                 if (root.getUri().equals(currentRoot.getUri())) {
                     // We don't need to change the current root as the current root was not removed.
                     return null;
                 }
             }
-            assert(homeRoot != null);
-            mHome = mOwner.getRootDocumentBlocking(homeRoot);
-            return homeRoot;
+            assert(downloadsRoot != null);
+            mDownloadsDocument = mOwner.getRootDocumentBlocking(downloadsRoot);
+            return downloadsRoot;
         }
 
         @Override
-        protected void finish(RootInfo homeRoot) {
-            if (homeRoot != null && mHome != null) {
+        protected void finish(RootInfo downloadsRoot) {
+            if (downloadsRoot != null && mDownloadsDocument != null) {
                 // Clear entire backstack and start in new root
-                mOwner.mState.onRootChanged(homeRoot);
-                mOwner.mSearchManager.update(homeRoot);
-                mOwner.openContainerDocument(mHome);
+                mOwner.mState.onRootChanged(downloadsRoot);
+                mOwner.mSearchManager.update(downloadsRoot);
+                mOwner.openContainerDocument(mDownloadsDocument);
             }
         }
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BootReceiver.java b/packages/DocumentsUI/src/com/android/documentsui/BootReceiver.java
new file mode 100644
index 0000000..cdea9d7
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/BootReceiver.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 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.documentsui;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Prime {@link RootsCache} when the system is booted.
+ */
+public class BootReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        // We already spun up our application object before getting here, which
+        // kicked off a task to load roots, so this broadcast is finished once
+        // that first pass is done.
+        DocumentsApplication.getRootsCache(context).setBootCompletedResult(goAsync());
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
deleted file mode 100644
index 000b92a..0000000
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.LinearLayout;
-
-public class DirectoryView extends LinearLayout {
-    private float mPosition = 0f;
-
-    private int mWidth;
-
-    public DirectoryView(Context context) {
-        super(context);
-    }
-
-    public DirectoryView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        super.onSizeChanged(w, h, oldw, oldh);
-        mWidth = w;
-        setPosition(mPosition);
-    }
-
-    public float getPosition() {
-        return mPosition;
-    }
-
-    public void setPosition(float position) {
-        mPosition = position;
-        setX((mWidth > 0) ? (mPosition * mWidth) : 0);
-
-        if (mPosition != 0) {
-            setTranslationZ(getResources().getDimensionPixelSize(R.dimen.dir_elevation));
-        } else {
-            setTranslationZ(0);
-        }
-    }
-}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 12a4186..ba593dc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -22,7 +22,6 @@
 import static com.android.documentsui.State.ACTION_OPEN;
 import static com.android.documentsui.State.ACTION_OPEN_TREE;
 import static com.android.documentsui.State.ACTION_PICK_COPY_DESTINATION;
-import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -46,6 +45,7 @@
 
 import com.android.documentsui.RecentsProvider.RecentColumns;
 import com.android.documentsui.RecentsProvider.ResumeColumns;
+import com.android.documentsui.dirlist.AnimationView;
 import com.android.documentsui.dirlist.DirectoryFragment;
 import com.android.documentsui.dirlist.Model;
 import com.android.documentsui.model.DocumentInfo;
@@ -95,7 +95,7 @@
         }
 
         if (mState.restored) {
-            refreshCurrentRootAndDirectory(ANIM_NONE);
+            if (DEBUG) Log.d(TAG, "Stack already resolved");
         } else {
             // We set the activity title in AsyncTask.onPostExecute().
             // To prevent talkback from reading aloud the default title, we clear it here.
@@ -108,9 +108,7 @@
             // we restore the stack as last used from that app.
             if (mState.action == ACTION_PICK_COPY_DESTINATION) {
                 if (DEBUG) Log.d(TAG, "Launching directly into Home directory.");
-                Uri homeUri = DocumentsContract.buildHomeUri();
-                new LoadRootTask(this, homeUri).executeOnExecutor(
-                        ProviderExecutor.forAuthority(homeUri.getAuthority()));
+                loadRoot(DocumentsContract.buildHomeUri());
             } else {
                 if (DEBUG) Log.d(TAG, "Attempting to load last used stack for calling package.");
                 new LoadLastUsedStackTask(this).execute();
@@ -156,30 +154,6 @@
         }
     }
 
-    private void onStackRestored(boolean restored, boolean external) {
-        // Show drawer when no stack restored, but only when requesting
-        // non-visual content. However, if we last used an external app,
-        // drawer is always shown.
-
-        boolean showDrawer = false;
-        if (!restored) {
-            showDrawer = true;
-        }
-        if (MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, mState.acceptMimes)) {
-            showDrawer = false;
-        }
-        if (external && mState.action == ACTION_GET_CONTENT) {
-            showDrawer = true;
-        }
-        if (mState.action == ACTION_PICK_COPY_DESTINATION) {
-            showDrawer = true;
-        }
-
-        if (showDrawer) {
-            mNavigator.revealRootsDrawer(true);
-        }
-    }
-
     public void onAppPicked(ResolveInfo info) {
         final Intent intent = new Intent(getIntent());
         intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_FORWARD_RESULT);
@@ -517,8 +491,8 @@
         @Override
         protected void finish(Void result) {
             mState.restored = true;
-            mOwner.refreshCurrentRootAndDirectory(ANIM_NONE);
-            mOwner.onStackRestored(mRestoredStack, mExternal);
+            mState.external = mExternal;
+            mOwner.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE);
         }
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
deleted file mode 100644
index 2f784cb..0000000
--- a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui;
-
-import static com.android.documentsui.State.ACTION_MANAGE;
-import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
-
-import android.app.Activity;
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.content.ActivityNotFoundException;
-import android.content.ClipData;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.DocumentsContract;
-import android.support.design.widget.Snackbar;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.widget.Toolbar;
-
-import com.android.documentsui.dirlist.DirectoryFragment;
-import com.android.documentsui.dirlist.Model;
-import com.android.documentsui.model.DocumentInfo;
-import com.android.documentsui.model.RootInfo;
-
-import java.util.Arrays;
-import java.util.List;
-
-// Let's face it. MANAGE_ROOT is used almost exclusively
-// for downloads, and is specialized for this purpose.
-// So it is now thusly christened.
-public class DownloadsActivity extends BaseActivity {
-    private static final String TAG = "DownloadsActivity";
-
-    public DownloadsActivity() {
-        super(R.layout.downloads_activity, TAG);
-    }
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        final Context context = this;
-
-        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
-        toolbar.setTitleTextAppearance(context,
-                android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
-
-        if (!mState.restored) {
-            // In this case, we set the activity title in AsyncTask.onPostExecute(). To prevent
-            // talkback from reading aloud the default title, we clear it here.
-            setTitle("");
-            final Uri rootUri = getIntent().getData();
-            new LoadRootTask(this, rootUri).executeOnExecutor(getExecutorForCurrentDirectory());
-        } else {
-            refreshCurrentRootAndDirectory(ANIM_NONE);
-        }
-    }
-
-    @Override
-    void includeState(State state) {
-        state.action = ACTION_MANAGE;
-        state.acceptMimes = new String[] { "*/*" };
-        state.allowMultiple = true;
-        state.showSize = true;
-        state.excludedAuthorities = getExcludedAuthorities();
-    }
-
-    @Override
-    protected void onPostCreate(Bundle savedInstanceState) {
-        super.onPostCreate(savedInstanceState);
-        mNavigator.update();
-    }
-
-    @Override
-    public String getDrawerTitle() {
-        return null;  // being and nothingness
-    }
-
-    @Override
-    public boolean onPrepareOptionsMenu(Menu menu) {
-        super.onPrepareOptionsMenu(menu);
-
-        final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
-        final MenuItem pasteFromCb = menu.findItem(R.id.menu_paste_from_clipboard);
-        final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
-
-        createDir.setVisible(false);
-        pasteFromCb.setEnabled(false);
-        fileSize.setVisible(false);
-
-        Menus.disableHiddenItems(menu);
-        return true;
-    }
-
-    @Override
-    void refreshDirectory(int anim) {
-        final FragmentManager fm = getFragmentManager();
-        final RootInfo root = getCurrentRoot();
-        final DocumentInfo cwd = getCurrentDirectory();
-
-        assert(!mSearchManager.isSearching());
-
-        // If started in manage roots mode, there has to be a cwd (i.e. the root dir of the managed
-        // root).
-        assert(cwd != null);
-
-        // Normal boring directory
-        DirectoryFragment.showDirectory(fm, root, cwd, anim);
-    }
-
-    @Override
-    public void onDocumentPicked(DocumentInfo doc, Model model) {
-        assert(!doc.isDirectory());
-
-        // First try managing the document; we expect manager to filter
-        // based on authority, so we don't grant.
-        final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT);
-        manage.setData(doc.derivedUri);
-
-        try {
-            startActivity(manage);
-        } catch (ActivityNotFoundException ex) {
-            // Fall back to viewing.
-            final Intent view = new Intent(Intent.ACTION_VIEW);
-            view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-            view.setData(doc.derivedUri);
-
-            try {
-                startActivity(view);
-            } catch (ActivityNotFoundException ex2) {
-                Snackbars.makeSnackbar(this, R.string.toast_no_application, Snackbar.LENGTH_SHORT)
-                        .show();
-            }
-        }
-    }
-
-    @Override
-    public void onDocumentsPicked(List<DocumentInfo> docs) {}
-
-    @Override
-    void onTaskFinished(Uri... uris) {
-        Log.d(TAG, "onFinished() " + Arrays.toString(uris));
-
-        final Intent intent = new Intent();
-        if (uris.length == 1) {
-            intent.setData(uris[0]);
-        } else if (uris.length > 1) {
-            final ClipData clipData = new ClipData(
-                    null, mState.acceptMimes, new ClipData.Item(uris[0]));
-            for (int i = 1; i < uris.length; i++) {
-                clipData.addItem(new ClipData.Item(uris[i]));
-            }
-            intent.setClipData(clipData);
-        }
-
-        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
-                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
-
-        setResult(Activity.RESULT_OK, intent);
-        finish();
-    }
-
-    public static DownloadsActivity get(Fragment fragment) {
-        return (DownloadsActivity) fragment.getActivity();
-    }
-}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index c56a12f..99f306a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -18,7 +18,6 @@
 
 import static com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_UNKNOWN;
 import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
 
 import android.app.Activity;
 import android.app.FragmentManager;
@@ -39,6 +38,7 @@
 
 import com.android.documentsui.OperationDialogFragment.DialogType;
 import com.android.documentsui.RecentsProvider.ResumeColumns;
+import com.android.documentsui.dirlist.AnimationView;
 import com.android.documentsui.dirlist.DirectoryFragment;
 import com.android.documentsui.dirlist.Model;
 import com.android.documentsui.model.DocumentInfo;
@@ -97,7 +97,7 @@
             if (DEBUG) Log.d(TAG, "Launching with non-empty stack.");
             assert(uri == null || uri.getAuthority() == null ||
                     LauncherActivity.isLaunchUri(uri));
-            refreshCurrentRootAndDirectory(ANIM_NONE);
+            refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE);
         } else if (intent.getAction() == Intent.ACTION_VIEW) {
             assert(uri != null);
             new OpenUriForViewTask(this).executeOnExecutor(
@@ -108,10 +108,10 @@
             // authority. That way a misbehaving provider won't result in an ANR.
             loadRoot(uri);
         } else {
-            if (DEBUG) Log.d(TAG, "Launching into Home directory.");
-            // If all else fails, try to load "Home" directory.
-            final Uri homeUri = DocumentsContract.buildHomeUri();
-            loadRoot(homeUri);
+            if (DEBUG) Log.d(TAG, "All other means skipped. Launching into default directory.");
+            Uri defaultUri = DocumentsContract.buildRootUri(
+                    "com.android.providers.downloads.documents", "downloads");
+            loadRoot(defaultUri);
         }
 
         final @DialogType int dialogType = intent.getIntExtra(
@@ -283,10 +283,16 @@
      */
     private void openDocument(DocumentInfo doc, Model model) {
 
-        // Provide specialized handling of downloaded APKs This sends the APK
-        // details off to get extra security information added, and finally
-        // to be handled by the package manager.
-        if (MimePredicate.isApkType(doc.mimeType)) {
+        // Anything on downloads goes through the back through downloads manager
+        // (that's the MANAGE_DOCUMENT bit).
+        // This is done for two reasons:
+        // 1) The file in question might be a failed/queued or otherwise have some
+        //    specialized download handling.
+        // 2) For APKs, the download manager will add on some important security stuff
+        //    like origin URL.
+        // All other files not on downloads, event APKs, would get no benefit from this
+        // treatment, thusly the "isDownloads" check.
+        if (getCurrentRoot().isDownloads()) {
             // First try managing the document; we expect manager to filter
             // based on authority, so we don't grant.
             final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT);
@@ -470,7 +476,7 @@
 
         @Override
         protected void finish(Void result) {
-            mOwner.refreshCurrentRootAndDirectory(ANIM_NONE);
+            mOwner.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE);
         }
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
index c7c61c3..8c4859f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
@@ -16,10 +16,20 @@
 
 package com.android.documentsui;
 
+import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.Shared.TAG;
 import static com.android.documentsui.State.MODE_UNKNOWN;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
 import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.UserHandle;
 import android.preference.PreferenceManager;
+import android.util.Log;
 
 import com.android.documentsui.State.ViewMode;
 import com.android.documentsui.model.RootInfo;
@@ -29,29 +39,73 @@
     private static final String ROOT_VIEW_MODE_PREFIX = "rootViewMode-";
 
     public static boolean getDisplayFileSize(Context context) {
-        return PreferenceManager.getDefaultSharedPreferences(context)
-                .getBoolean(KEY_FILE_SIZE, false);
+        return getPrefs(context).getBoolean(KEY_FILE_SIZE, false);
     }
 
-    public static @ViewMode int getViewMode(
-            Context context, RootInfo root, @ViewMode int fallback) {
-        return PreferenceManager.getDefaultSharedPreferences(context)
-                .getInt(createKey(root), fallback);
+    public static @ViewMode int getViewMode(Context context, RootInfo root,
+            @ViewMode int fallback) {
+        return getPrefs(context).getInt(createKey(root), fallback);
     }
 
     public static void setDisplayFileSize(Context context, boolean display) {
-        PreferenceManager.getDefaultSharedPreferences(context).edit()
-                .putBoolean(KEY_FILE_SIZE, display).apply();
+        getPrefs(context).edit().putBoolean(KEY_FILE_SIZE, display).apply();
     }
 
     public static void setViewMode(Context context, RootInfo root, @ViewMode int viewMode) {
         assert(viewMode != MODE_UNKNOWN);
 
-        PreferenceManager.getDefaultSharedPreferences(context).edit()
-                .putInt(createKey(root), viewMode).apply();
+        getPrefs(context).edit().putInt(createKey(root), viewMode).apply();
+    }
+
+    private static SharedPreferences getPrefs(Context context) {
+        return PreferenceManager.getDefaultSharedPreferences(context);
     }
 
     private static String createKey(RootInfo root) {
         return ROOT_VIEW_MODE_PREFIX + root.authority + root.rootId;
     }
+
+    public static final int PERMISSION_ASK = 0;
+    public static final int PERMISSION_ASK_AGAIN = 1;
+    public static final int PERMISSION_NEVER_ASK = -1;
+
+    @IntDef(flag = true, value = {
+            PERMISSION_ASK,
+            PERMISSION_ASK_AGAIN,
+            PERMISSION_NEVER_ASK,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PermissionStatus {}
+
+    /**
+     * Methods below are used to keep track of denied user requests on scoped directory access so
+     * the dialog is not offered when user checked the 'Do not ask again' box
+     *
+     * <p>It uses a shared preferences, whose key is:
+     * <ol>
+     * <li>{@code USER_ID|PACKAGE_NAME|VOLUME_UUID|DIRECTORY} for storage volumes that have a UUID
+     * (typically physical volumes like SD cards).
+     * <li>{@code USER_ID|PACKAGE_NAME||DIRECTORY} for storage volumes that do not have a UUID
+     * (typically the emulated volume used for primary storage
+     * </ol>
+     */
+    static @PermissionStatus int getScopedAccessPermissionStatus(Context context,
+            String packageName, @Nullable String uuid, String directory) {
+        final String key = getScopedAccessDenialsKey(packageName, uuid, directory);
+        return getPrefs(context).getInt(key, PERMISSION_ASK);
+    }
+
+    static void setScopedAccessPermissionStatus(Context context, String packageName,
+            @Nullable String uuid, String directory, @PermissionStatus int status) {
+      final String key = getScopedAccessDenialsKey(packageName, uuid, directory);
+      getPrefs(context).edit().putInt(key, status).apply();
+    }
+
+    private static String getScopedAccessDenialsKey(String packageName, String uuid,
+            String directory) {
+        final int userId = UserHandle.myUserId();
+        return uuid == null
+                ? userId + "|" + packageName + "||" + directory
+                : userId + "|" + packageName + "|" + uuid + "|" + directory;
+    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
index dcaea15..deef1c2 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
@@ -18,6 +18,7 @@
 
 import static android.os.Environment.STANDARD_DIRECTORIES;
 import static com.android.documentsui.Shared.DEBUG;
+
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.StringDef;
@@ -58,7 +59,7 @@
     private static final String COUNT_CREATE_MIME = "docsui_create_mime";
     private static final String COUNT_GET_CONTENT_MIME = "docsui_get_content_mime";
     private static final String COUNT_BROWSE_ROOT = "docsui_browse_root";
-    private static final String COUNT_MANAGE_ROOT = "docsui_manage_root";
+    @Deprecated private static final String COUNT_MANAGE_ROOT = "docsui_manage_root";
     private static final String COUNT_MULTI_WINDOW = "docsui_multi_window";
     private static final String COUNT_FILEOP_SYSTEM = "docsui_fileop_system";
     private static final String COUNT_FILEOP_EXTERNAL = "docsui_fileop_external";
@@ -194,7 +195,7 @@
     private static final int ACTION_CREATE = 3;
     private static final int ACTION_GET_CONTENT = 4;
     private static final int ACTION_OPEN_TREE = 5;
-    private static final int ACTION_MANAGE = 6;
+    @Deprecated private static final int ACTION_MANAGE = 6;
     private static final int ACTION_BROWSE = 7;
     private static final int ACTION_PICK_COPY_DESTINATION = 8;
 
@@ -246,9 +247,6 @@
             case State.ACTION_GET_CONTENT:
                 logHistogram(context, COUNT_GET_CONTENT_MIME, sanitizeMime(intent.getType()));
                 break;
-            case State.ACTION_MANAGE:
-                logHistogram(context, COUNT_MANAGE_ROOT, sanitizeRoot(uri));
-                break;
             case State.ACTION_BROWSE:
                 logHistogram(context, COUNT_BROWSE_ROOT, sanitizeRoot(uri));
                 break;
@@ -413,11 +411,15 @@
     public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED = 0;
     public static final int SCOPED_DIRECTORY_ACCESS_GRANTED = 1;
     public static final int SCOPED_DIRECTORY_ACCESS_DENIED = 2;
+    public static final int SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST = 3;
+    public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED = 4;
 
     @IntDef(flag = true, value = {
             SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED,
             SCOPED_DIRECTORY_ACCESS_GRANTED,
-            SCOPED_DIRECTORY_ACCESS_DENIED
+            SCOPED_DIRECTORY_ACCESS_DENIED,
+            SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST,
+            SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ScopedAccessGrant {}
@@ -434,23 +436,34 @@
         final String packageName = activity.getCallingPackage();
         switch (type) {
             case SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED:
-                MetricsLogger.action(activity,
-                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE,
-                        packageName);
-                MetricsLogger.action(activity,
-                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER, index);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE, packageName);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER, index);
                 break;
             case SCOPED_DIRECTORY_ACCESS_GRANTED:
-                MetricsLogger.action(activity,
-                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE, packageName);
-                MetricsLogger.action(activity,
-                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER, index);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE, packageName);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER, index);
                 break;
             case SCOPED_DIRECTORY_ACCESS_DENIED:
-                MetricsLogger.action(activity,
-                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE, packageName);
-                MetricsLogger.action(activity,
-                        MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER, index);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE, packageName);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER, index);
+                break;
+            case SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST:
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_PACKAGE, packageName);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_FOLDER, index);
+                break;
+            case SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED:
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_PACKAGE, packageName);
+                MetricsLogger.action(activity, MetricsEvent
+                        .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_FOLDER, index);
                 break;
             default:
                 Log.wtf(TAG, "invalid ScopedAccessGrant: " + type);
@@ -641,8 +654,6 @@
                 return ACTION_GET_CONTENT;
             case State.ACTION_OPEN_TREE:
                 return ACTION_OPEN_TREE;
-            case State.ACTION_MANAGE:
-                return ACTION_MANAGE;
             case State.ACTION_BROWSE:
                 return ACTION_BROWSE;
             case State.ACTION_PICK_COPY_DESTINATION:
diff --git a/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java b/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
index c520204..30c1020 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
@@ -19,7 +19,6 @@
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_LEAVE;
 
 import android.annotation.Nullable;
 import android.graphics.drawable.Drawable;
@@ -30,10 +29,10 @@
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemSelectedListener;
 import android.widget.BaseAdapter;
-import android.widget.ImageView;
 import android.widget.Spinner;
 import android.widget.TextView;
 
+import com.android.documentsui.dirlist.AnimationView;
 import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.model.RootInfo;
 
@@ -105,7 +104,7 @@
         while (mState.stack.size() > position + 1) {
             mState.popDocument();
         }
-        mEnv.refreshCurrentRootAndDirectory(ANIM_LEAVE);
+        mEnv.refreshCurrentRootAndDirectory(AnimationView.ANIM_LEAVE);
     }
 
     void update() {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
index dc529ce..2b6f396 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
@@ -20,16 +20,24 @@
 import static android.os.Environment.STANDARD_DIRECTORIES;
 import static android.os.storage.StorageVolume.EXTRA_DIRECTORY_NAME;
 import static android.os.storage.StorageVolume.EXTRA_STORAGE_VOLUME;
-import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.Metrics.logInvalidScopedAccessRequest;
-import static com.android.documentsui.Metrics.logValidScopedAccessRequest;
+import static com.android.documentsui.LocalPreferences.getScopedAccessPermissionStatus;
+import static com.android.documentsui.LocalPreferences.PERMISSION_ASK;
+import static com.android.documentsui.LocalPreferences.PERMISSION_ASK_AGAIN;
+import static com.android.documentsui.LocalPreferences.PERMISSION_NEVER_ASK;
+import static com.android.documentsui.LocalPreferences.setScopedAccessPermissionStatus;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED;
 import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED;
 import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_DENIED;
+import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST;
 import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ERROR;
 import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_GRANTED;
 import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS;
 import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY;
+import static com.android.documentsui.Metrics.logInvalidScopedAccessRequest;
+import static com.android.documentsui.Metrics.logValidScopedAccessRequest;
+import static com.android.documentsui.Shared.DEBUG;
 
+import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.AlertDialog;
@@ -38,7 +46,6 @@
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
 import android.content.ContentProviderClient;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
@@ -57,6 +64,11 @@
 import android.provider.DocumentsContract;
 import android.text.TextUtils;
 import android.util.Log;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.TextView;
 
 import java.io.File;
 import java.io.IOException;
@@ -72,12 +84,17 @@
     private static final String EXTRA_FILE = "com.android.documentsui.FILE";
     private static final String EXTRA_APP_LABEL = "com.android.documentsui.APP_LABEL";
     private static final String EXTRA_VOLUME_LABEL = "com.android.documentsui.VOLUME_LABEL";
+    private static final String EXTRA_VOLUME_UUID = "com.android.documentsui.VOLUME_UUID";
 
     private ContentProviderClient mExternalStorageClient;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        if (savedInstanceState != null) {
+            if (DEBUG) Log.d(TAG, "activity.onCreateDialog(): reusing instance");
+            return;
+        }
 
         final Intent intent = getIntent();
         if (intent == null) {
@@ -105,9 +122,18 @@
             finish();
             return;
         }
+        final StorageVolume volume = (StorageVolume) storageVolume;
+        if (getScopedAccessPermissionStatus(getApplicationContext(), getCallingPackage(),
+                volume.getUuid(), directoryName) == PERMISSION_NEVER_ASK) {
+            logValidScopedAccessRequest(this, directoryName,
+                    SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED);
+            setResult(RESULT_CANCELED);
+            finish();
+            return;
+        }
 
         final int userId = UserHandle.myUserId();
-        if (!showFragment(this, userId, (StorageVolume) storageVolume, directoryName)) {
+        if (!showFragment(this, userId, volume, directoryName)) {
             setResult(RESULT_CANCELED);
             finish();
             return;
@@ -157,6 +183,7 @@
 
         // Gets volume label and converted path.
         String volumeLabel = null;
+        String volumeUuid = null;
         final List<VolumeInfo> volumes = sm.getVolumes();
         if (DEBUG) Log.d(TAG, "Number of volumes: " + volumes.size());
         for (VolumeInfo volume : volumes) {
@@ -166,6 +193,7 @@
                 if (DEBUG) Log.d(TAG, "Converting " + root + " to " + internalRoot);
                 file = new File(internalRoot, directory);
                 volumeLabel = sm.getBestVolumeDescription(volume);
+                volumeUuid = volume.getFsUuid();
                 break;
             }
         }
@@ -197,6 +225,7 @@
         final Bundle args = new Bundle();
         args.putString(EXTRA_FILE, file.getAbsolutePath());
         args.putString(EXTRA_VOLUME_LABEL, volumeLabel);
+        args.putString(EXTRA_VOLUME_UUID, volumeUuid);
         args.putString(EXTRA_APP_LABEL, appLabel);
 
         final FragmentManager fm = activity.getFragmentManager();
@@ -303,16 +332,21 @@
     public static class OpenExternalDirectoryDialogFragment extends DialogFragment {
 
         private File mFile;
+        private String mVolumeUuid;
         private String mVolumeLabel;
         private String mAppLabel;
+        private CheckBox mDontAskAgain;
         private OpenExternalDirectoryActivity mActivity;
+        private AlertDialog mDialog;
 
         @Override
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
+            setRetainInstance(true);
             final Bundle args = getArguments();
             if (args != null) {
                 mFile = new File(args.getString(EXTRA_FILE));
+                mVolumeUuid = args.getString(EXTRA_VOLUME_UUID);
                 mVolumeLabel = args.getString(EXTRA_VOLUME_LABEL);
                 mAppLabel = args.getString(EXTRA_APP_LABEL);
             }
@@ -320,9 +354,28 @@
         }
 
         @Override
+        public void onDestroyView() {
+            // Workaround for https://code.google.com/p/android/issues/detail?id=17423
+            if (mDialog != null && getRetainInstance()) {
+                mDialog.setDismissMessage(null);
+            }
+            super.onDestroyView();
+        }
+
+        @Override
         public Dialog onCreateDialog(Bundle savedInstanceState) {
+            if (mDialog != null) {
+                if (DEBUG) Log.d(TAG, "fragment.onCreateDialog(): reusing dialog");
+                return mDialog;
+            }
+            if (mActivity != getActivity()) {
+                // Sanity check.
+                Log.wtf(TAG, "activity references don't match on onCreateDialog(): mActivity = "
+                        + mActivity + " , getActivity() = " + getActivity());
+                mActivity = (OpenExternalDirectoryActivity) getActivity();
+            }
             final String directory = mFile.getName();
-            final Activity activity = getActivity();
+            final Context context = mActivity.getApplicationContext();
             final OnClickListener listener = new OnClickListener() {
 
                 @Override
@@ -333,15 +386,25 @@
                                 mActivity.getExternalStorageClient(), mFile);
                     }
                     if (which == DialogInterface.BUTTON_NEGATIVE || intent == null) {
-                        logValidScopedAccessRequest(activity, directory,
+                        logValidScopedAccessRequest(mActivity, directory,
                                 SCOPED_DIRECTORY_ACCESS_DENIED);
-                        activity.setResult(RESULT_CANCELED);
+                        final boolean checked = mDontAskAgain.isChecked();
+                        if (checked) {
+                            logValidScopedAccessRequest(mActivity, directory,
+                                    SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST);
+                            setScopedAccessPermissionStatus(context, mActivity.getCallingPackage(),
+                                    mVolumeUuid, directory, PERMISSION_NEVER_ASK);
+                        } else {
+                            setScopedAccessPermissionStatus(context, mActivity.getCallingPackage(),
+                                    mVolumeUuid, directory, PERMISSION_ASK_AGAIN);
+                        }
+                        mActivity.setResult(RESULT_CANCELED);
                     } else {
-                        logValidScopedAccessRequest(activity, directory,
+                        logValidScopedAccessRequest(mActivity, directory,
                                 SCOPED_DIRECTORY_ACCESS_GRANTED);
-                        activity.setResult(RESULT_OK, intent);
+                        mActivity.setResult(RESULT_OK, intent);
                     }
-                    activity.finish();
+                    mActivity.finish();
                 }
             };
 
@@ -349,11 +412,31 @@
                     .expandTemplate(
                             getText(R.string.open_external_dialog_request), mAppLabel, directory,
                             mVolumeLabel);
-            return new AlertDialog.Builder(activity, R.style.AlertDialogTheme)
-                    .setMessage(message)
+            @SuppressLint("InflateParams")
+            // It's ok pass null ViewRoot on AlertDialogs.
+            final View view = View.inflate(mActivity, R.layout.dialog_open_scoped_directory, null);
+            final TextView messageField = (TextView) view.findViewById(R.id.message);
+            messageField.setText(message);
+            mDialog = new AlertDialog.Builder(mActivity, R.style.Theme_AppCompat_Light_Dialog_Alert)
+                    .setView(view)
                     .setPositiveButton(R.string.allow, listener)
                     .setNegativeButton(R.string.deny, listener)
                     .create();
+
+            mDontAskAgain = (CheckBox) view.findViewById(R.id.do_not_ask_checkbox);
+            if (getScopedAccessPermissionStatus(context, mActivity.getCallingPackage(),
+                    mVolumeUuid, directory) == PERMISSION_ASK_AGAIN) {
+                mDontAskAgain.setVisibility(View.VISIBLE);
+                mDontAskAgain.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+
+                    @Override
+                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                        mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(!isChecked);
+                    }
+                });
+            }
+
+            return mDialog;
         }
 
         @Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
index a77a9b3..8fcd9d1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
@@ -113,8 +113,8 @@
     }
 
     private int collectViewableUris(ArrayList<Uri> uris) {
-        final List<String> siblingIds = mModel.getModelIds();
-        uris.ensureCapacity(siblingIds.size());
+        final String[] siblingIds = mModel.getModelIds();
+        uris.ensureCapacity(siblingIds.length);
 
         int documentLocation = 0;
         Cursor cursor;
@@ -124,8 +124,8 @@
         Uri uri;
 
         // Cursor's are not guaranteed to be immutable. Hence, traverse it only once.
-        for (int i = 0; i < siblingIds.size(); i++) {
-            cursor = mModel.getItem(siblingIds.get(i));
+        for (int i = 0; i < siblingIds.length; i++) {
+            cursor = mModel.getItem(siblingIds[i]);
 
             mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
             if (Document.MIME_TYPE_DIR.equals(mimeType)) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index 2b7294a..6efe9c8 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -18,6 +18,7 @@
 
 import static com.android.documentsui.Shared.DEBUG;
 
+import android.content.BroadcastReceiver.PendingResult;
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -30,6 +31,7 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.SystemClock;
 import android.provider.DocumentsContract;
@@ -40,11 +42,11 @@
 import com.android.documentsui.model.RootInfo;
 import com.android.internal.annotations.GuardedBy;
 
+import libcore.io.IoUtils;
+
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Multimap;
 
-import libcore.io.IoUtils;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -63,6 +65,8 @@
 
     private static final String TAG = "RootsCache";
 
+    private static final boolean ENABLE_SYSTEM_CACHE = true;
+
     private final Context mContext;
     private final ContentObserver mObserver;
     private OnCacheUpdateListener mCacheUpdateListener;
@@ -73,6 +77,11 @@
     private final CountDownLatch mFirstLoad = new CountDownLatch(1);
 
     @GuardedBy("mLock")
+    private boolean mFirstLoadDone;
+    @GuardedBy("mLock")
+    private PendingResult mBootCompletedResult;
+
+    @GuardedBy("mLock")
     private Multimap<String, RootInfo> mRoots = ArrayListMultimap.create();
     @GuardedBy("mLock")
     private HashSet<String> mStoppedAuthorities = new HashSet<>();
@@ -118,7 +127,7 @@
     public void updateAsync() {
 
         // NOTE: This method is called when the UI language changes.
-        // For that reason we upadte our RecentsRoot to reflect
+        // For that reason we update our RecentsRoot to reflect
         // the current language.
         mRecentsRoot.title = mContext.getString(R.string.root_recent);
 
@@ -152,7 +161,25 @@
         }
     }
 
-    private void waitForFirstLoad() {
+    public void setBootCompletedResult(PendingResult result) {
+        synchronized (mLock) {
+            // Quickly check if we've already finished loading, otherwise hang
+            // out until first pass is finished.
+            if (mFirstLoadDone) {
+                result.finish();
+            } else {
+                mBootCompletedResult = result;
+            }
+        }
+    }
+
+    /**
+     * Block until the first {@link UpdateTask} pass has finished.
+     *
+     * @return {@code true} if cached roots is ready to roll, otherwise
+     *         {@code false} if we timed out while waiting.
+     */
+    private boolean waitForFirstLoad() {
         boolean success = false;
         try {
             success = mFirstLoad.await(15, TimeUnit.SECONDS);
@@ -161,6 +188,7 @@
         if (!success) {
             Log.w(TAG, "Timeout waiting for first update");
         }
+        return success;
     }
 
     /**
@@ -222,9 +250,11 @@
             final long start = SystemClock.elapsedRealtime();
 
             if (mFilterPackage != null) {
-                // Need at least first load, since we're going to be using
-                // previously cached values for non-matching packages.
-                waitForFirstLoad();
+                // We must have previously cached values to fill in non-matching
+                // packages, so wait around for successful first load.
+                if (!waitForFirstLoad()) {
+                    return null;
+                }
             }
 
             mTaskRoots.put(mRecentsRoot.authority, mRecentsRoot);
@@ -243,6 +273,11 @@
             if (DEBUG)
                 Log.d(TAG, "Update found " + mTaskRoots.size() + " roots in " + delta + "ms");
             synchronized (mLock) {
+                mFirstLoadDone = true;
+                if (mBootCompletedResult != null) {
+                    mBootCompletedResult.finish();
+                    mBootCompletedResult = null;
+                }
                 mRoots = mTaskRoots;
                 mStoppedAuthorities = mTaskStoppedAuthorities;
             }
@@ -300,9 +335,18 @@
             }
         }
 
-        final List<RootInfo> roots = new ArrayList<>();
         final Uri rootsUri = DocumentsContract.buildRootsUri(authority);
+        if (ENABLE_SYSTEM_CACHE) {
+            // Look for roots data that we might have cached for ourselves in the
+            // long-lived system process.
+            final Bundle systemCache = resolver.getCache(rootsUri);
+            if (systemCache != null) {
+                if (DEBUG) Log.d(TAG, "System cache hit for " + authority);
+                return systemCache.getParcelableArrayList(TAG);
+            }
+        }
 
+        final ArrayList<RootInfo> roots = new ArrayList<>();
         ContentProviderClient client = null;
         Cursor cursor = null;
         try {
@@ -318,6 +362,16 @@
             IoUtils.closeQuietly(cursor);
             ContentProviderClient.releaseQuietly(client);
         }
+
+        if (ENABLE_SYSTEM_CACHE) {
+            // Cache these freshly parsed roots over in the long-lived system
+            // process, in case our process goes away. The system takes care of
+            // invalidating the cache if the package or Uri changes.
+            final Bundle systemCache = new Bundle();
+            systemCache.putParcelableArrayList(TAG, roots);
+            resolver.putCache(rootsUri, systemCache);
+        }
+
         return roots;
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 26900a7..c32bbff 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -86,11 +86,10 @@
      */
     public static final String EXTRA_IGNORE_STATE = "ignoreState";
 
-
     /**
-     * String prefix used to indicate the document is a directory.
+     * Extra for an Intent for enabling performance benchmark. Used only by tests.
      */
-    public static final char DIR_PREFIX = '\001';
+    public static final String EXTRA_BENCHMARK = "com.android.documentsui.benchmark";
 
     private static final Collator sCollator;
 
@@ -139,8 +138,7 @@
 
     /**
      * Compare two strings against each other using system default collator in a
-     * case-insensitive mode. Clusters strings prefixed with {@link DIR_PREFIX}
-     * before other items.
+     * case-insensitive mode.
      */
     public static int compareToIgnoreCaseNullable(String lhs, String rhs) {
         final boolean leftEmpty = TextUtils.isEmpty(lhs);
@@ -150,12 +148,6 @@
         if (leftEmpty) return -1;
         if (rightEmpty) return 1;
 
-        final boolean leftDir = (lhs.charAt(0) == DIR_PREFIX);
-        final boolean rightDir = (rhs.charAt(0) == DIR_PREFIX);
-
-        if (leftDir && !rightDir) return -1;
-        if (rightDir && !leftDir) return 1;
-
         return sCollator.compare(lhs, rhs);
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/State.java b/packages/DocumentsUI/src/com/android/documentsui/State.java
index 4f460b4..16b7660 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/State.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/State.java
@@ -43,13 +43,15 @@
 
     private static final String TAG = "State";
 
-    public static final int ACTION_OPEN = 1;
-    public static final int ACTION_CREATE = 2;
-    public static final int ACTION_GET_CONTENT = 3;
-    public static final int ACTION_OPEN_TREE = 4;
-    public static final int ACTION_MANAGE = 5;
-    public static final int ACTION_BROWSE = 6;
-    public static final int ACTION_PICK_COPY_DESTINATION = 8;
+    // File manager and related private picking activity.
+    public static final int ACTION_BROWSE = 1;
+    public static final int ACTION_PICK_COPY_DESTINATION = 2;
+
+    // All public picking activities
+    public static final int ACTION_OPEN = 3;
+    public static final int ACTION_CREATE = 4;
+    public static final int ACTION_GET_CONTENT = 5;
+    public static final int ACTION_OPEN_TREE = 6;
 
     @IntDef(flag = true, value = {
             MODE_UNKNOWN,
@@ -83,6 +85,10 @@
     public boolean showSize;
     public boolean localOnly;
     public boolean restored;
+    /*
+     * Indicates handler was an external app, like photos.
+     */
+    public boolean external;
 
     // Indicates that a copy operation (or move) includes a directory.
     // Why? Directory creation isn't supported by some roots (like Downloads).
@@ -180,6 +186,7 @@
         out.writeInt(showSize ? 1 : 0);
         out.writeInt(localOnly ? 1 : 0);
         out.writeInt(restored ? 1 : 0);
+        out.writeInt(external ? 1 : 0);
         DurableUtils.writeToParcel(out, stack);
         out.writeMap(dirState);
         out.writeParcelable(selectedDocuments, 0);
@@ -208,6 +215,7 @@
             state.showSize = in.readInt() != 0;
             state.localOnly = in.readInt() != 0;
             state.restored = in.readInt() != 0;
+            state.external = in.readInt() != 0;
             DurableUtils.readFromParcel(in, state.stack);
             in.readMap(state.dirState, loader);
             state.selectedDocuments = in.readParcelable(loader);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/AnimationView.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/AnimationView.java
new file mode 100644
index 0000000..a666456
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/AnimationView.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.dirlist;
+
+import android.annotation.IntDef;
+import android.app.FragmentTransaction;
+import android.content.Context;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+
+import com.android.documentsui.R;
+import com.android.documentsui.Shared;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This class exists solely to support animated transition of our directory fragment.
+ * The structure of this class is tightly coupled with the static animations defined in
+ * res/animator, specifically the "position" property referenced by
+ * res/animator/dir_{enter,leave}.xml.
+ */
+public class AnimationView extends LinearLayout {
+
+    @IntDef(flag = true, value = {
+            ANIM_NONE,
+            ANIM_SIDE,
+            ANIM_LEAVE,
+            ANIM_ENTER
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AnimationType {}
+    public static final int ANIM_NONE = 1;
+    public static final int ANIM_SIDE = 2;
+    public static final int ANIM_LEAVE = 3;
+    public static final int ANIM_ENTER = 4;
+
+    private float mPosition = 0f;
+
+    // The distance the animation will cover...currently matches the height of the
+    // content area.
+    private int mSpan;
+
+    public AnimationView(Context context) {
+        super(context);
+    }
+
+    public AnimationView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        mSpan = h;
+        setPosition(mPosition);
+    }
+
+    public float getPosition() {
+        return mPosition;
+    }
+
+    public void setPosition(float position) {
+        mPosition = position;
+        // Warning! If we ever decide to switch this to setX (slide left/right)
+        // please remember to add RLT variations of the animations under res/animator-ldrtl.
+        setY((mSpan > 0) ? (mPosition * mSpan) : 0);
+
+        if (mPosition != 0) {
+            setTranslationZ(getResources().getDimensionPixelSize(R.dimen.dir_elevation));
+        } else {
+            setTranslationZ(0);
+        }
+    }
+
+    /**
+     * Configures custom animations on the transaction according to the specified
+     * @AnimationType.
+     */
+    static void setupAnimations(
+            FragmentTransaction ft, @AnimationType int anim, Bundle args) {
+        switch (anim) {
+            case AnimationView.ANIM_SIDE:
+                args.putBoolean(Shared.EXTRA_IGNORE_STATE, true);
+                break;
+            case AnimationView.ANIM_ENTER:
+                // TODO: Document which behavior is being tailored
+                //     by passing this bit. Remove if possible.
+                args.putBoolean(Shared.EXTRA_IGNORE_STATE, true);
+                ft.setCustomAnimations(R.animator.dir_enter, R.animator.fade_out);
+                break;
+            case AnimationView.ANIM_LEAVE:
+                ft.setCustomAnimations(R.animator.fade_in, R.animator.dir_leave);
+                break;
+        }
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index ca1b444..63a834f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -84,7 +84,6 @@
 import com.android.documentsui.Events.MotionInputEvent;
 import com.android.documentsui.Menus;
 import com.android.documentsui.MessageBar;
-import com.android.documentsui.MimePredicate;
 import com.android.documentsui.R;
 import com.android.documentsui.RecentsLoader;
 import com.android.documentsui.RootsCache;
@@ -99,7 +98,6 @@
 import com.android.documentsui.services.FileOperationService;
 import com.android.documentsui.services.FileOperationService.OpType;
 import com.android.documentsui.services.FileOperations;
-
 import com.google.common.collect.Lists;
 
 import java.lang.annotation.Retention;
@@ -125,19 +123,6 @@
     public static final int TYPE_RECENT_OPEN = 2;
 
     @IntDef(flag = true, value = {
-            ANIM_NONE,
-            ANIM_SIDE,
-            ANIM_LEAVE,
-            ANIM_ENTER
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface AnimationType {}
-    public static final int ANIM_NONE = 1;
-    public static final int ANIM_SIDE = 2;
-    public static final int ANIM_LEAVE = 3;
-    public static final int ANIM_ENTER = 4;
-
-    @IntDef(flag = true, value = {
             REQUEST_COPY_DESTINATION
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -179,6 +164,7 @@
     private String mQuery = null;
     private Selection mSelection = null;
     private boolean mSearchMode = false;
+    private @Nullable ActionMode mActionMode;
 
     @Override
     public View onCreateView(
@@ -281,16 +267,6 @@
         mTuner = FragmentTuner.pick(getContext(), state);
         mClipper = new DocumentClipper(context);
 
-        boolean hideGridTitles;
-        if (mType == TYPE_RECENT_OPEN) {
-            // Hide titles when showing recents for picking images/videos
-            hideGridTitles = MimePredicate.mimeMatches(
-                    MimePredicate.VISUAL_MIMES, state.acceptMimes);
-        } else {
-            hideGridTitles = (mDocument != null) && mDocument.isGridTitlesHidden();
-        }
-        GridDocumentHolder.setHideTitles(hideGridTitles);
-
         final ActivityManager am = (ActivityManager) context.getSystemService(
                 Context.ACTIVITY_SERVICE);
         boolean svelte = am.isLowRamDevice() && (mType == TYPE_RECENT_OPEN);
@@ -430,9 +406,9 @@
         int cellMargin = 2 * getResources().getDimensionPixelSize(R.dimen.grid_item_margin);
         int viewPadding = mRecView.getPaddingLeft() + mRecView.getPaddingRight();
 
-        assert(mRecView.getWidth() > 0);
-
-        int columnCount = Math.max(1,
+        // RecyclerView sometimes gets a width of 0 (see b/27150284).  Clamp so that we always lay
+        // out the grid with at least 2 columns.
+        int columnCount = Math.max(2,
                 (mRecView.getWidth() - viewPadding) / (cellWidth + cellMargin));
 
         return columnCount;
@@ -463,7 +439,7 @@
             implements MultiSelectManager.Callback, ActionMode.Callback {
 
         private Selection mSelected = new Selection();
-        private ActionMode mActionMode;
+        private int mNoCopyCount = 0;
         private int mNoDeleteCount = 0;
         private int mNoRenameCount = -1;
         private Menu mMenu;
@@ -495,6 +471,9 @@
             // triggered on "silent" selection updates (i.e. we might be reacting to unfinalized
             // selection changes here)
             final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
+            if ((docFlags & Document.FLAG_PARTIAL) != 0) {
+                mNoCopyCount += selected ? 1 : -1;
+            }
             if ((docFlags & Document.FLAG_SUPPORTS_DELETE) == 0
                     && (docFlags & Document.FLAG_SUPPORTS_DELETE) == 0) {
                 mNoDeleteCount += selected ? 1 : -1;
@@ -561,19 +540,24 @@
             return true;
         }
 
-        boolean canRenameSelection() {
-            return mNoRenameCount == 0 && mSelectionManager.getSelection().size() == 1;
+        boolean canCopySelection() {
+            return mNoCopyCount == 0;
         }
 
         boolean canDeleteSelection() {
             return mNoDeleteCount == 0;
         }
 
+        boolean canRenameSelection() {
+            return mNoRenameCount == 0 && mSelectionManager.getSelection().size() == 1;
+        }
+
         private void updateActionMenu() {
             assert(mMenu != null);
 
             // Delegate update logic to our owning action, since specialized logic is desired.
-            mTuner.updateActionMenu(mMenu, mType, canDeleteSelection(), canRenameSelection());
+            mTuner.updateActionMenu(
+                    mMenu, mType, canCopySelection(), canDeleteSelection(), canRenameSelection());
             Menus.disableHiddenItems(mMenu);
         }
 
@@ -593,10 +577,9 @@
                     return true;
 
                 case R.id.menu_delete:
-                    // Pass mode along to the delete function so it can
-                    // end action mode when documents are deleted.
+                    // deleteDocuments will end action mode if the documents are deleted.
                     // It won't end action mode if user cancels the delete.
-                    deleteDocuments(selection, mode);
+                    deleteDocuments(selection);
                     return true;
 
                 case R.id.menu_copy_to:
@@ -705,7 +688,7 @@
         }.execute(selected);
     }
 
-    private void deleteDocuments(final Selection selected, final ActionMode mode) {
+    private void deleteDocuments(final Selection selected) {
         assert(!selected.isEmpty());
 
         final DocumentInfo srcParent = getDisplayState().stack.peek();
@@ -742,7 +725,9 @@
                                 // This is done here, rather in the onActionItemClicked
                                 // so we can avoid de-selecting items in the case where
                                 // the user cancels the delete.
-                                mode.finish();
+                                if (mActionMode != null) {
+                                    mActionMode.finish();
+                                }
                                 // Hide the files in the UI...since the operation
                                 // might be queued up on FileOperationService.
                                 // We're walking a line here.
@@ -1278,12 +1263,25 @@
             }
 
             // Handle enter key events
-            if (keyCode == KeyEvent.KEYCODE_ENTER) {
-                if (event.isShiftPressed()) {
-                    return onSelect(doc);
-                } else {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_ENTER:
+                    if (event.isShiftPressed()) {
+                        return onSelect(doc);
+                    }
+                    // For non-shifted enter keypresses, fall through.
+                case KeyEvent.KEYCODE_DPAD_CENTER:
+                case KeyEvent.KEYCODE_BUTTON_A:
                     return onActivate(doc);
-                }
+                case KeyEvent.KEYCODE_FORWARD_DEL:
+                    // This has to be handled here instead of in a keyboard shortcut, because
+                    // keyboard shortcuts all have to be modified with the 'Ctrl' key.
+                    if (mSelectionManager.hasSelection()) {
+                        deleteDocuments(mSelectionManager.getSelection());
+                    }
+                    // Always handle the key, even if there was nothing to delete. This is a
+                    // precaution to prevent other handlers from potentially picking up the event
+                    // and triggering extra behaviours.
+                    return true;
             }
 
             return false;
@@ -1495,18 +1493,7 @@
         args.putParcelable(Shared.EXTRA_SELECTION, new Selection());
 
         final FragmentTransaction ft = fm.beginTransaction();
-        switch (anim) {
-            case ANIM_SIDE:
-                args.putBoolean(Shared.EXTRA_IGNORE_STATE, true);
-                break;
-            case ANIM_ENTER:
-                args.putBoolean(Shared.EXTRA_IGNORE_STATE, true);
-                ft.setCustomAnimations(R.animator.dir_enter, R.animator.dir_frozen);
-                break;
-            case ANIM_LEAVE:
-                ft.setCustomAnimations(R.animator.dir_frozen, R.animator.dir_leave);
-                break;
-        }
+        AnimationView.setupAnimations(ft, anim, args);
 
         final DirectoryFragment fragment = new DirectoryFragment();
         fragment.setArguments(args);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
index 3b5ce87..450341f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
@@ -16,6 +16,7 @@
 
 package com.android.documentsui.dirlist;
 
+import android.annotation.ColorInt;
 import android.content.Context;
 import android.database.Cursor;
 import android.graphics.Rect;
@@ -35,17 +36,19 @@
         extends RecyclerView.ViewHolder
         implements View.OnKeyListener {
 
+    static final float DISABLED_ALPHA = 0.3f;
+
     public @Nullable String modelId;
 
-    final int mSelectedItemColor;
-    final int mDefaultItemColor;
-    final boolean mAlwaysShowSummary;
     final Context mContext;
+    final @ColorInt int mDefaultBgColor;
+    final @ColorInt int mSelectedBgColor;
 
     DocumentHolder.EventListener mEventListener;
     private View.OnKeyListener mKeyListener;
     private View mSelectionHotspot;
 
+
     public DocumentHolder(Context context, ViewGroup parent, int layout) {
         this(context, inflateLayout(context, parent, layout));
     }
@@ -57,9 +60,8 @@
 
         mContext = context;
 
-        mDefaultItemColor = context.getColor(R.color.item_doc_background);
-        mSelectedItemColor = context.getColor(R.color.item_doc_background_selected);
-        mAlwaysShowSummary = context.getResources().getBoolean(R.bool.always_show_summary);
+        mDefaultBgColor = context.getColor(R.color.item_doc_background);
+        mSelectedBgColor = context.getColor(R.color.item_doc_background_selected);
 
         mSelectionHotspot = itemView.findViewById(R.id.icon_check);
     }
@@ -75,12 +77,20 @@
     /**
      * Makes the associated item view appear selected. Note that this merely affects the appearance
      * of the view, it doesn't actually select the item.
+     * TODO: Use the DirectoryItemAnimator instead of manually controlling animation using a boolean
+     * flag.
      *
      * @param selected
+     * @param animate Whether or not to animate the change. Only selection changes initiated by the
+     *            selection manager should be animated. See
+     *            {@link ModelBackedDocumentsAdapter#onBindViewHolder(DocumentHolder, int, java.util.List)}
      */
-    public void setSelected(boolean selected) {
+    public void setSelected(boolean selected, boolean animate) {
+        // Note: the animate param doesn't apply for this base implementation, because the
+        // DirectoryItemAnimator takes care of it. It's required by subclasses, which perform their
+        // own animation.
         itemView.setActivated(selected);
-        itemView.setBackgroundColor(selected ? mSelectedItemColor : mDefaultItemColor);
+        itemView.setBackgroundColor(selected ? mSelectedBgColor : mDefaultBgColor);
     }
 
     /**
@@ -88,7 +98,11 @@
      * @param highlighted
      */
     public void setHighlighted(boolean highlighted) {
-        itemView.setBackgroundColor(highlighted ? mSelectedItemColor : mDefaultItemColor);
+        itemView.setBackgroundColor(highlighted ? mSelectedBgColor : mDefaultBgColor);
+    }
+
+    public void setEnabled(boolean enabled) {
+        setEnabledRecursive(itemView, enabled);
     }
 
     @Override
@@ -111,10 +125,6 @@
         mKeyListener = listener;
     }
 
-    public void setEnabled(boolean enabled) {
-        setEnabledRecursive(itemView, enabled);
-    }
-
     public boolean onSingleTapUp(MotionEvent event) {
         if (Events.isMouseEvent(event)) {
             // Mouse clicks select.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
index adaa850..ea1deb4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
@@ -19,9 +19,9 @@
 import static com.android.documentsui.State.ACTION_BROWSE;
 import static com.android.documentsui.State.ACTION_CREATE;
 import static com.android.documentsui.State.ACTION_GET_CONTENT;
-import static com.android.documentsui.State.ACTION_MANAGE;
 import static com.android.documentsui.State.ACTION_OPEN;
 import static com.android.documentsui.State.ACTION_OPEN_TREE;
+import static com.android.documentsui.State.ACTION_PICK_COPY_DESTINATION;
 
 import android.content.Context;
 import android.provider.DocumentsContract.Document;
@@ -53,16 +53,14 @@
         switch (state.action) {
             case ACTION_BROWSE:
                 return new FilesTuner(context, state);
-            case ACTION_MANAGE:
-                return new DownloadsTuner(context, state);
             default:
                 return new DocumentsTuner(context, state);
         }
     }
 
-
     public abstract void updateActionMenu(
-            Menu menu, @ResultType int dirType, boolean canDelete, boolean canRename);
+            Menu menu, @ResultType int dirType,
+            boolean canCopy, boolean canDelete, boolean canRename);
 
     // Subtly different from isDocumentEnabled. The reason may be illuminated as follows.
     // A folder is enabled such that it may be double clicked, even in settings
@@ -106,7 +104,8 @@
                 return false;
             }
 
-            if (mState.action == ACTION_OPEN_TREE) {
+            if (mState.action == ACTION_OPEN_TREE
+                    || mState.action == ACTION_PICK_COPY_DESTINATION) {
                 // In this case nothing *ever* is selectable...the expected user behavior is
                 // they navigate *into* a folder, then click a confirmation button indicating
                 // that the current directory is the directory they are picking.
@@ -142,7 +141,8 @@
 
         @Override
         public void updateActionMenu(
-                Menu menu, @ResultType int dirType, boolean canDelete, boolean canRename) {
+                Menu menu, @ResultType int dirType,
+                boolean canCopy, boolean canDelete, boolean canRename) {
 
             MenuItem open = menu.findItem(R.id.menu_open);
             MenuItem share = menu.findItem(R.id.menu_share);
@@ -157,8 +157,27 @@
 
         @Override
         void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch) {
+            boolean showDrawer = false;
+
+            if (mState.restored) {
+                showDrawer = true;
+            }
+            if (MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, mState.acceptMimes)) {
+                showDrawer = false;
+            }
+            if (mState.external && mState.action == ACTION_GET_CONTENT) {
+                showDrawer = true;
+            }
+            if (mState.action == ACTION_PICK_COPY_DESTINATION) {
+                showDrawer = true;
+            }
+
             // When launched into empty root, open drawer.
-            if (model.isEmpty() && !mState.hasInitialLocationChanged() && !isSearch) {
+            if (model.isEmpty()) {
+                showDrawer = true;
+            }
+
+            if (showDrawer && !mState.hasInitialLocationChanged() && !isSearch) {
                 // This noops on layouts without drawer, so no need to guard.
                 ((BaseActivity) mContext).setRootsDrawerOpen(true);
             }
@@ -171,47 +190,6 @@
     }
 
     /**
-     * Provides support for Platform specific specializations of DirectoryFragment.
-     */
-    private static final class DownloadsTuner extends FragmentTuner {
-
-        public DownloadsTuner(Context context, State state) {
-            super(context, state);
-            assert(state.action == ACTION_MANAGE);
-        }
-
-        @Override
-        public void updateActionMenu(
-                Menu menu, @ResultType int resultType, boolean canDelete, boolean canRename) {
-            assert(resultType != DirectoryFragment.TYPE_RECENT_OPEN);
-
-            MenuItem open = menu.findItem(R.id.menu_open);
-            MenuItem delete = menu.findItem(R.id.menu_delete);
-            MenuItem copyTo = menu.findItem(R.id.menu_copy_to);
-            MenuItem moveTo = menu.findItem(R.id.menu_move_to);
-            MenuItem rename = menu.findItem(R.id.menu_rename);
-            MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
-
-            open.setVisible(false);
-            delete.setVisible(canDelete);
-            copy.setEnabled(true);  // to clipboard
-            copyTo.setVisible(true);
-            copyTo.setEnabled(true);
-            moveTo.setVisible(true);
-            moveTo.setEnabled(true);
-            rename.setVisible(false);
-        }
-
-        @Override
-        void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch) {}
-
-        @Override
-        public boolean enableManagedMode() {
-            return mState.stack.root != null && mState.stack.root.isDownloads();
-        }
-    }
-
-    /**
      * Provides support for Files activity specific specializations of DirectoryFragment.
      */
     private static final class FilesTuner extends FragmentTuner {
@@ -222,22 +200,28 @@
 
         @Override
         public void updateActionMenu(
-                Menu menu, @ResultType int dirType, boolean canDelete, boolean canRename) {
+                Menu menu, @ResultType int dirType,
+                boolean canCopy, boolean canDelete, boolean canRename) {
 
             MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
             MenuItem paste = menu.findItem(R.id.menu_paste_from_clipboard);
-            copy.setEnabled(dirType != DirectoryFragment.TYPE_RECENT_OPEN);
+            copy.setEnabled(canCopy);
 
             MenuItem rename = menu.findItem(R.id.menu_rename);
+            MenuItem moveTo = menu.findItem(R.id.menu_move_to);
+            MenuItem copyTo = menu.findItem(R.id.menu_copy_to);
+
+            copyTo.setVisible(true);
+            moveTo.setVisible(true);
             rename.setVisible(true);
+
+            copyTo.setEnabled(canCopy);
+            moveTo.setEnabled(canCopy && canDelete);
             rename.setEnabled(canRename);
 
             menu.findItem(R.id.menu_share).setVisible(true);
             menu.findItem(R.id.menu_delete).setVisible(canDelete);
             menu.findItem(R.id.menu_open).setVisible(false);
-            menu.findItem(R.id.menu_copy_to).setVisible(true);
-            menu.findItem(R.id.menu_move_to).setVisible(true);
-            menu.findItem(R.id.menu_move_to).setEnabled(canDelete);
 
             Menus.disableHiddenItems(menu, copy, paste);
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
index 90b2341..ce5bcb1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java
@@ -42,12 +42,17 @@
     }
 
     @Override
-    public void setSelected(boolean selected) {
-        super.setSelected(selected);
+    public void setSelected(boolean selected, boolean animate) {
+        super.setSelected(selected, animate);
         float checkAlpha = selected ? 1f : 0f;
 
-        mIconCheck.animate().alpha(checkAlpha).start();
-        mIconMime.animate().alpha(1f - checkAlpha).start();
+        if (animate) {
+            mIconCheck.animate().alpha(checkAlpha).start();
+            mIconMime.animate().alpha(1f - checkAlpha).start();
+        } else {
+            mIconCheck.setAlpha(checkAlpha);
+            mIconMime.setAlpha(1f - checkAlpha);
+        }
     }
 
     /**
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
index a4bce16..c4f6f11 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java
@@ -20,6 +20,7 @@
 import static com.android.documentsui.model.DocumentInfo.getCursorLong;
 import static com.android.documentsui.model.DocumentInfo.getCursorString;
 
+import android.annotation.ColorInt;
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
@@ -37,6 +38,7 @@
 import com.android.documentsui.State;
 
 final class GridDocumentHolder extends DocumentHolder {
+
     private static boolean mHideTitles;
 
     final TextView mTitle;
@@ -48,9 +50,13 @@
     final ImageView mIconCheck;
     final IconHelper mIconHelper;
 
+    private final @ColorInt int mDisabledBgColor;
+
     public GridDocumentHolder(Context context, ViewGroup parent, IconHelper iconHelper) {
         super(context, parent, R.layout.item_doc_grid);
 
+        mDisabledBgColor = context.getColor(R.color.item_doc_background_disabled);
+
         mTitle = (TextView) itemView.findViewById(android.R.id.title);
         mDate = (TextView) itemView.findViewById(R.id.date);
         mSize = (TextView) itemView.findViewById(R.id.size);
@@ -63,12 +69,42 @@
     }
 
     @Override
-    public void setSelected(boolean selected) {
-        super.setSelected(selected);
+    public void setSelected(boolean selected, boolean animate) {
+        // We always want to make sure our check box disappears if we're not selected,
+        // even if the item is disabled. This is because this object can be reused
+        // and this method will be called to setup initial state.
         float checkAlpha = selected ? 1f : 0f;
+        if (animate) {
+            mIconCheck.animate().alpha(checkAlpha).start();
+        } else {
+            mIconCheck.setAlpha(checkAlpha);
+        }
 
-        mIconCheck.animate().alpha(checkAlpha).start();
-        mIconMimeSm.animate().alpha(1f - checkAlpha).start();
+        // But it should be an error to be set to selected && be disabled.
+        if (!itemView.isEnabled()) {
+            assert(!selected);
+            return;
+        }
+
+        super.setSelected(selected, animate);
+
+        if (animate) {
+            mIconMimeSm.animate().alpha(1f - checkAlpha).start();
+        } else {
+            mIconMimeSm.setAlpha(1f - checkAlpha);
+        }
+    }
+
+    public void setEnabled(boolean enabled) {
+        super.setEnabled(enabled);
+
+        // Text colors enabled/disabled is handle via a color set.
+        itemView.setBackgroundColor(enabled ? mDefaultBgColor : mDisabledBgColor);
+        float imgAlpha = enabled ? 1f : DISABLED_ALPHA;
+
+        mIconMimeLg.setAlpha(imgAlpha);
+        mIconMimeSm.setAlpha(imgAlpha);
+        mIconThumb.setAlpha(imgAlpha);
     }
 
     /**
@@ -122,12 +158,4 @@
             mSize.setText(Formatter.formatFileSize(mContext, docSize));
         }
     }
-
-    /**
-     * Sets whether to hide titles on subsequently created GridDocumentHolder items.
-     * @param hideTitles
-     */
-    public static void setHideTitles(boolean hideTitles) {
-        mHideTitles = hideTitles;
-    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
index 0831dbf..ace53e0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
@@ -65,13 +65,41 @@
     }
 
     @Override
-    public void setSelected(boolean selected) {
-        super.setSelected(selected);
+    public void setSelected(boolean selected, boolean animate) {
+        // We always want to make sure our check box disappears if we're not selected,
+        // even if the item is disabled. But it should be an error (see assert below)
+        // to be set to selected && be disabled.
         float checkAlpha = selected ? 1f : 0f;
+        if (animate) {
+            mIconCheck.animate().alpha(checkAlpha).start();
+        } else {
+            mIconCheck.setAlpha(checkAlpha);
+        }
 
-        mIconCheck.animate().alpha(checkAlpha).start();
-        mIconMime.animate().alpha(1f - checkAlpha).start();
-        mIconThumb.animate().alpha(1f - checkAlpha).start();
+        if (!itemView.isEnabled()) {
+            assert(!selected);
+            return;
+        }
+
+        super.setSelected(selected, animate);
+
+        if (animate) {
+            mIconMime.animate().alpha(1f - checkAlpha).start();
+            mIconThumb.animate().alpha(1f - checkAlpha).start();
+        } else {
+            mIconMime.setAlpha(1f - checkAlpha);
+            mIconThumb.setAlpha(1f - checkAlpha);
+        }
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        super.setEnabled(enabled);
+
+        // Text colors enabled/disabled is handle via a color set.
+        final float imgAlpha = enabled ? 1f : DISABLED_ALPHA;
+        mIconMime.setAlpha(imgAlpha);
+        mIconThumb.setAlpha(imgAlpha);
     }
 
     /**
@@ -145,12 +173,4 @@
             mDetails.setVisibility(hasDetails ? View.VISIBLE : View.GONE);
         }
     }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        super.setEnabled(enabled);
-        final float iconAlpha = enabled ? 1f : 0.5f;
-        mIconMime.setAlpha(iconAlpha);
-        mIconThumb.setAlpha(iconAlpha);
-    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
index 8170e2a..c5ee592 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
@@ -59,7 +59,7 @@
      * A sorted array of model IDs for the files currently in the Model.  Sort order is determined
      * by {@link #mSortOrder}
      */
-    private List<String> mIds = new ArrayList<>();
+    private String mIds[] = new String[0];
     private int mSortOrder = SORT_ORDER_DISPLAY_NAME;
 
     @Nullable String info;
@@ -108,7 +108,7 @@
         if (result == null) {
             mCursor = null;
             mCursorCount = 0;
-            mIds.clear();
+            mIds = new String[0];
             mPositions.clear();
             info = null;
             error = null;
@@ -152,74 +152,81 @@
      */
     private void updateModelData() {
         int[] positions = new int[mCursorCount];
-        mIds.clear();
-        String[] stringValues = new String[mCursorCount];
+        mIds = new String[mCursorCount];
+        boolean[] isDirs = new boolean[mCursorCount];
+        String[] displayNames = null;
         long[] longValues = null;
 
-        if (mSortOrder == SORT_ORDER_LAST_MODIFIED || mSortOrder == SORT_ORDER_SIZE) {
-            longValues = new long[mCursorCount];
+        switch (mSortOrder) {
+            case SORT_ORDER_DISPLAY_NAME:
+                displayNames = new String[mCursorCount];
+                break;
+            case SORT_ORDER_LAST_MODIFIED:
+            case SORT_ORDER_SIZE:
+                longValues = new long[mCursorCount];
+                break;
         }
 
+        String mimeType;
+
         mCursor.moveToPosition(-1);
         for (int pos = 0; pos < mCursorCount; ++pos) {
             mCursor.moveToNext();
             positions[pos] = pos;
-            mIds.add(createModelId(mCursor));
+            mIds[pos] = createModelId(mCursor);
+
+            mimeType = getCursorString(mCursor, Document.COLUMN_MIME_TYPE);
+            isDirs[pos] = Document.MIME_TYPE_DIR.equals(mimeType);
 
             switch(mSortOrder) {
                 case SORT_ORDER_DISPLAY_NAME:
-                    final String mimeType = getCursorString(mCursor, Document.COLUMN_MIME_TYPE);
                     final String displayName = getCursorString(
                             mCursor, Document.COLUMN_DISPLAY_NAME);
-                    if (Document.MIME_TYPE_DIR.equals(mimeType)) {
-                        stringValues[pos] = Shared.DIR_PREFIX + displayName;
-                    } else {
-                        stringValues[pos] = displayName;
-                    }
+                    displayNames[pos] = displayName;
                     break;
                 case SORT_ORDER_LAST_MODIFIED:
                     longValues[pos] = getLastModified(mCursor);
-                    stringValues[pos] = getCursorString(mCursor, Document.COLUMN_MIME_TYPE);
                     break;
                 case SORT_ORDER_SIZE:
                     longValues[pos] = getCursorLong(mCursor, Document.COLUMN_SIZE);
-                    stringValues[pos] = getCursorString(mCursor, Document.COLUMN_MIME_TYPE);
                     break;
             }
         }
 
         switch (mSortOrder) {
             case SORT_ORDER_DISPLAY_NAME:
-                binarySort(stringValues, positions, mIds);
+                binarySort(displayNames, isDirs, positions, mIds);
                 break;
             case SORT_ORDER_LAST_MODIFIED:
             case SORT_ORDER_SIZE:
-                binarySort(longValues, stringValues, positions, mIds);
+                binarySort(longValues, isDirs, positions, mIds);
                 break;
         }
 
         // Populate the positions.
         mPositions.clear();
         for (int i = 0; i < mCursorCount; ++i) {
-            mPositions.put(mIds.get(i), positions[i]);
+            mPositions.put(mIds[i], positions[i]);
         }
     }
 
     /**
      * Sorts model data. Takes three columns of index-corresponded data. The first column is the
-     * sort key. Rows are sorted in ascending alphabetical order on the sort key. This code is based
-     * on TimSort.binarySort().
+     * sort key. Rows are sorted in ascending alphabetical order on the sort key.
+     * Directories are always shown first. This code is based on TimSort.binarySort().
      *
      * @param sortKey Data is sorted in ascending alphabetical order.
+     * @param isDirs Array saying whether an item is a directory or not.
      * @param positions Cursor positions to be sorted.
      * @param ids Model IDs to be sorted.
      */
-    private static void binarySort(String[] sortKey, int[] positions, List<String> ids) {
+    private static void binarySort(String[] sortKey, boolean[] isDirs, int[] positions, String[] ids) {
         final int count = positions.length;
         for (int start = 1; start < count; start++) {
             final int pivotPosition = positions[start];
             final String pivotValue = sortKey[start];
-            final String pivotId = ids.get(start);
+            final boolean pivotIsDir = isDirs[start];
+            final String pivotId = ids[start];
 
             int left = 0;
             int right = start;
@@ -227,9 +234,18 @@
             while (left < right) {
                 int mid = (left + right) >>> 1;
 
-                final String lhs = pivotValue;
-                final String rhs = sortKey[mid];
-                final int compare = Shared.compareToIgnoreCaseNullable(lhs, rhs);
+                // Directories always go in front.
+                int compare = 0;
+                final boolean rhsIsDir = isDirs[mid];
+                if (pivotIsDir && !rhsIsDir) {
+                    compare = -1;
+                } else if (!pivotIsDir && rhsIsDir) {
+                    compare = 1;
+                } else {
+                    final String lhs = pivotValue;
+                    final String rhs = sortKey[mid];
+                    compare = Shared.compareToIgnoreCaseNullable(lhs, rhs);
+                }
 
                 if (compare < 0) {
                     right = mid;
@@ -243,23 +259,25 @@
                 case 2:
                     positions[left + 2] = positions[left + 1];
                     sortKey[left + 2] = sortKey[left + 1];
-                    ids.set(left + 2, ids.get(left + 1));
+                    isDirs[left + 2] = isDirs[left + 1];
+                    ids[left + 2] = ids[left + 1];
                 case 1:
                     positions[left + 1] = positions[left];
                     sortKey[left + 1] = sortKey[left];
-                    ids.set(left + 1, ids.get(left));
+                    isDirs[left + 1] = isDirs[left];
+                    ids[left + 1] = ids[left];
                     break;
                 default:
                     System.arraycopy(positions, left, positions, left + 1, n);
                     System.arraycopy(sortKey, left, sortKey, left + 1, n);
-                    for (int i = n; i >= 1; --i) {
-                        ids.set(left + i, ids.get(left + i - 1));
-                    }
+                    System.arraycopy(isDirs, left, isDirs, left + 1, n);
+                    System.arraycopy(ids, left, ids, left + 1, n);
             }
 
             positions[left] = pivotPosition;
             sortKey[left] = pivotValue;
-            ids.set(left, pivotId);
+            isDirs[left] = pivotIsDir;
+            ids[left] = pivotId;
         }
     }
 
@@ -270,18 +288,18 @@
      * numerical order on the sort key. This code is based on TimSort.binarySort().
      *
      * @param sortKey Data is sorted in descending numerical order.
-     * @param mimeTypes Corresponding mime types. Directories will be sorted ahead of documents.
+     * @param isDirs Array saying whether an item is a directory or not.
      * @param positions Cursor positions to be sorted.
      * @param ids Model IDs to be sorted.
      */
     private static void binarySort(
-            long[] sortKey, String[] mimeTypes, int[] positions, List<String> ids) {
+            long[] sortKey, boolean[] isDirs, int[] positions, String[] ids) {
         final int count = positions.length;
         for (int start = 1; start < count; start++) {
             final int pivotPosition = positions[start];
             final long pivotValue = sortKey[start];
-            final String pivotMime = mimeTypes[start];
-            final String pivotId = ids.get(start);
+            final boolean pivotIsDir = isDirs[start];
+            final String pivotId = ids[start];
 
             int left = 0;
             int right = start;
@@ -289,13 +307,12 @@
             while (left < right) {
                 int mid = ((left + right) >>> 1);
 
-                // First bucket by mime type.  Directories always go in front.
+                // Directories always go in front.
                 int compare = 0;
-                final boolean lhsIsDir = Document.MIME_TYPE_DIR.equals(pivotMime);
-                final boolean rhsIsDir = Document.MIME_TYPE_DIR.equals(mimeTypes[mid]);
-                if (lhsIsDir && !rhsIsDir) {
+                final boolean rhsIsDir = isDirs[mid];
+                if (pivotIsDir && !rhsIsDir) {
                     compare = -1;
-                } else if (!lhsIsDir && rhsIsDir) {
+                } else if (!pivotIsDir && rhsIsDir) {
                     compare = 1;
                 } else {
                     final long lhs = pivotValue;
@@ -310,7 +327,7 @@
                 // have identical numerical sort keys.  One common example of this scenario is seen
                 // when sorting a set of active downloads by mod time.
                 if (compare == 0) {
-                    compare = pivotId.compareTo(ids.get(mid));
+                    compare = pivotId.compareTo(ids[mid]);
                 }
 
                 if (compare < 0) {
@@ -325,27 +342,25 @@
                 case 2:
                     positions[left + 2] = positions[left + 1];
                     sortKey[left + 2] = sortKey[left + 1];
-                    mimeTypes[left + 2] = mimeTypes[left + 1];
-                    ids.set(left + 2, ids.get(left + 1));
+                    isDirs[left + 2] = isDirs[left + 1];
+                    ids[left + 2] = ids[left + 1];
                 case 1:
                     positions[left + 1] = positions[left];
                     sortKey[left + 1] = sortKey[left];
-                    mimeTypes[left + 1] = mimeTypes[left];
-                    ids.set(left + 1, ids.get(left));
+                    isDirs[left + 1] = isDirs[left];
+                    ids[left + 1] = ids[left];
                     break;
                 default:
                     System.arraycopy(positions, left, positions, left + 1, n);
                     System.arraycopy(sortKey, left, sortKey, left + 1, n);
-                    System.arraycopy(mimeTypes, left, mimeTypes, left + 1, n);
-                    for (int i = n; i >= 1; --i) {
-                        ids.set(left + i, ids.get(left + i - 1));
-                    }
+                    System.arraycopy(isDirs, left, isDirs, left + 1, n);
+                    System.arraycopy(ids, left, ids, left + 1, n);
             }
 
             positions[left] = pivotPosition;
             sortKey[left] = pivotValue;
-            mimeTypes[left] = pivotMime;
-            ids.set(left, pivotId);
+            isDirs[left] = pivotIsDir;
+            ids[left] = pivotId;
         }
     }
 
@@ -413,7 +428,7 @@
      * @return An ordered array of model IDs representing the documents in the model. It is sorted
      *         according to the current sort order, which was set by the last model update.
      */
-    public List<String> getModelIds() {
+    public String[] getModelIds() {
         return mIds;
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
index 2b07339..ca3b2e2 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
@@ -29,7 +29,6 @@
 import android.view.ViewGroup;
 
 import com.android.documentsui.State;
-
 import com.google.common.collect.Sets;
 
 import java.util.ArrayList;
@@ -103,7 +102,7 @@
     public void onBindViewHolder(DocumentHolder holder, int position, List<Object> payload) {
         if (payload.contains(SELECTION_CHANGED_MARKER)) {
             final boolean selected = mEnv.isSelected(mModelIds.get(position));
-            holder.setSelected(selected);
+            holder.setSelected(selected, true);
         } else {
             onBindViewHolder(holder, position);
         }
@@ -118,8 +117,13 @@
         final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
         final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
 
-        holder.setSelected(mEnv.isSelected(modelId));
-        holder.setEnabled(mEnv.isDocumentEnabled(docMimeType, docFlags));
+        boolean enabled = mEnv.isDocumentEnabled(docMimeType, docFlags);
+        boolean selected = mEnv.isSelected(modelId);
+        if (!enabled) {
+            assert(!selected);
+        }
+        holder.setEnabled(enabled);
+        holder.setSelected(mEnv.isSelected(modelId), false);
 
         mEnv.onBindDocumentHolder(holder, cursor);
     }
@@ -135,8 +139,8 @@
             Log.d(TAG, "Updating model with hidden ids: " + mHiddenIds);
         }
 
-        List<String> modelIds = model.getModelIds();
-        mModelIds = new ArrayList<>(modelIds.size());
+        String[] modelIds = model.getModelIds();
+        mModelIds = new ArrayList<>(modelIds.length);
         for (String id : modelIds) {
             if (!mHiddenIds.contains(id)) {
                 mModelIds.add(id);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
index b0cc09a..b80486d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
@@ -903,7 +903,7 @@
             public Selection createFromParcel(Parcel in, ClassLoader loader) {
                 return new Selection(
                         in.readString(),
-                        (ArrayList<String>) in.readArrayList(loader));
+                        in.readArrayList(loader));
             }
 
             @Override
@@ -931,7 +931,6 @@
         Rect getAbsoluteRectForChildViewAt(int index);
         int getAdapterPositionAt(int index);
         int getColumnCount();
-        int getRowCount();
         int getChildCount();
         int getVisibleChildCount();
         /**
@@ -1008,13 +1007,6 @@
         }
 
         @Override
-        public int getRowCount() {
-            int numFullColumns = getChildCount() / getColumnCount();
-            boolean hasPartiallyFullColumn = getChildCount() % getColumnCount() != 0;
-            return numFullColumns + (hasPartiallyFullColumn ? 1 : 0);
-        }
-
-        @Override
         public int getHeight() {
             return mView.getHeight();
         }
@@ -1202,6 +1194,7 @@
             }
 
             mCurrentPosition = input.getOrigin();
+            mModel.resizeSelection(input.getOrigin());
             scrollViewIfNecessary();
             resizeBandSelectRectangle();
         }
@@ -1549,11 +1542,7 @@
                         mColumnBounds, new Limits(absoluteChildRect.left, absoluteChildRect.right));
             }
 
-            if (mRowBounds.size() != mHelper.getRowCount()) {
-                // If not all y-limits have been recorded, record this one.
-                recordLimits(
-                        mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom));
-            }
+            recordLimits(mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom));
 
             SparseIntArray columnList = mColumns.get(absoluteChildRect.left);
             if (columnList == null) {
@@ -1747,6 +1736,11 @@
                 return ((Limits) other).lowerLimit == lowerLimit &&
                         ((Limits) other).upperLimit == upperLimit;
             }
+
+            @Override
+            public String toString() {
+                return "(" + lowerLimit + ", " + upperLimit + ")";
+            }
         }
 
         /**
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
index d74121e5..31ce837 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
@@ -74,7 +74,6 @@
         summary = null;
         size = -1;
         icon = 0;
-
         derivedUri = null;
     }
 
@@ -210,6 +209,7 @@
                 + ", isContainer=" + isContainer()
                 + ", isDirectory=" + isDirectory()
                 + ", isArchive=" + isArchive()
+                + ", isPartial=" + isPartial()
                 + ", isVirtualDocument=" + isVirtualDocument()
                 + ", isDeleteSupported=" + isDeleteSupported()
                 + ", isCreateSupported=" + isCreateSupported()
@@ -245,14 +245,14 @@
         return (flags & Document.FLAG_SUPPORTS_RENAME) != 0;
     }
 
-    public boolean isGridTitlesHidden() {
-        return (flags & Document.FLAG_DIR_HIDE_GRID_TITLES) != 0;
-    }
-
     public boolean isArchive() {
         return (flags & Document.FLAG_ARCHIVE) != 0;
     }
 
+    public boolean isPartial() {
+        return (flags & Document.FLAG_PARTIAL) != 0;
+    }
+
     public boolean isContainer() {
         return isDirectory() || isArchive();
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index 3eaf10a..3960475 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -55,7 +55,7 @@
     private static final int VERSION_DROP_TYPE = 2;
 
     // The values of these constants determine the sort order of various roots in the RootsFragment.
-    @IntDef(flag = true, value = {
+    @IntDef(flag = false, value = {
             TYPE_IMAGES,
             TYPE_VIDEO,
             TYPE_AUDIO,
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
index ad48a70..9ed2abf 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
@@ -299,18 +299,15 @@
             if ((src.flags & Document.FLAG_SUPPORTS_COPY) != 0) {
                 try {
                     if (DocumentsContract.copyDocument(getClient(src), src.derivedUri,
-                            dstDirInfo.derivedUri) == null) {
-                        throw new ResourceException("Provider side copy failed for document %s.",
-                                src.derivedUri);
+                            dstDirInfo.derivedUri) != null) {
+                        return;
                     }
-                } catch (ResourceException e) {
-                    throw e;
                 } catch (RemoteException | RuntimeException e) {
-                    throw new ResourceException(
-                            "Provider side copy failed for document %s due to an exception.",
-                            src.derivedUri, e);
+                    Log.e(TAG, "Provider side copy failed for: " + src.derivedUri
+                            + " due to an exception: " + e);
                 }
-                return;
+                // If optimized copy fails, then fallback to byte-by-byte copy.
+                if (DEBUG) Log.d(TAG, "Fallback to byte-by-byte copy for: " + src.derivedUri);
             }
         }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
index f1b4681..aaa7596 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
@@ -16,6 +16,7 @@
 
 package com.android.documentsui.services;
 
+import static com.android.documentsui.Shared.DEBUG;
 import static com.android.documentsui.services.FileOperationService.OPERATION_MOVE;
 
 import android.app.Notification;
@@ -24,6 +25,7 @@
 import android.os.RemoteException;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsContract.Document;
+import android.util.Log;
 
 import com.android.documentsui.R;
 import com.android.documentsui.model.DocumentInfo;
@@ -34,6 +36,8 @@
 // TODO: Stop extending CopyJob.
 final class MoveJob extends CopyJob {
 
+    private static final String TAG = "MoveJob";
+
     final DocumentInfo mSrcParent;
 
     /**
@@ -89,16 +93,15 @@
                 try {
                     if (DocumentsContract.moveDocument(getClient(src), src.derivedUri,
                             srcParent != null ? srcParent.derivedUri : mSrcParent.derivedUri,
-                            dest.derivedUri) == null) {
-                        throw new ResourceException("Provider side move failed for document %s.",
-                                src.derivedUri);
+                            dest.derivedUri) != null) {
+                        return;
                     }
-                } catch (RuntimeException | RemoteException e) {
-                    throw new ResourceException(
-                            "Provider side move failed for document %s due to an exception.",
-                            src.derivedUri, e);
+                } catch (RemoteException | RuntimeException e) {
+                    Log.e(TAG, "Provider side move failed for: " + src.derivedUri
+                            + " due to an exception: " + e);
                 }
-                return;
+                // If optimized move fails, then fallback to byte-by-byte copy.
+                if (DEBUG) Log.d(TAG, "Fallback to byte-by-byte move for: " + src.derivedUri);
             }
         }
 
diff --git a/packages/DocumentsUI/tests/AndroidManifest.xml b/packages/DocumentsUI/tests/AndroidManifest.xml
index a312427..b986285 100644
--- a/packages/DocumentsUI/tests/AndroidManifest.xml
+++ b/packages/DocumentsUI/tests/AndroidManifest.xml
@@ -2,6 +2,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.documentsui.tests">
 
+    <uses-permission android:name="android.permission.INTERNET" />
+
     <application>
         <uses-library android:name="android.test.runner" />
         <provider
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java
index af478ea..16ed2d9 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java
@@ -106,13 +106,15 @@
         return createDocument(root.documentId, mimeType, name);
     }
 
-    public Uri createDocumentWithFlags(String documentId, String mimeType, String name, int flags)
+    public Uri createDocumentWithFlags(String documentId, String mimeType, String name, int flags,
+            String... streamTypes)
             throws RemoteException {
         Bundle in = new Bundle();
         in.putInt(StubProvider.EXTRA_FLAGS, flags);
         in.putString(StubProvider.EXTRA_PARENT_ID, documentId);
         in.putString(Document.COLUMN_MIME_TYPE, mimeType);
         in.putString(Document.COLUMN_DISPLAY_NAME, name);
+        in.putStringArrayList(StubProvider.EXTRA_STREAM_TYPES, Lists.newArrayList(streamTypes));
 
         Bundle out = mClient.call("createDocumentWithFlags", null, in);
         Uri uri = out.getParcelable(DocumentsContract.EXTRA_URI);
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java
deleted file mode 100644
index 79d7887..0000000
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/DownloadsActivityUiTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.documentsui;
-
-import static com.android.documentsui.StubProvider.ROOT_0_ID;
-
-import android.content.Intent;
-import android.os.RemoteException;
-import android.provider.DocumentsContract;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.Until;
-import android.test.suitebuilder.annotation.LargeTest;
-
-@LargeTest
-public class DownloadsActivityUiTest extends ActivityTest<DownloadsActivity> {
-
-    public DownloadsActivityUiTest() {
-        super(DownloadsActivity.class);
-    }
-
-    @Override
-    void launchActivity() {
-        final Intent intent = new Intent(DocumentsContract.ACTION_MANAGE_ROOT);
-        intent.setDataAndType(rootDir0.getUri(), DocumentsContract.Root.MIME_TYPE_ITEM);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
-        setActivityIntent(intent);
-        getActivity();  // Launch the activity.
-    }
-
-    @Override
-    void initTestFiles() throws RemoteException {
-        mDocsHelper.createDocument(rootDir0, "text/plain", "file0.log");
-        mDocsHelper.createDocument(rootDir0, "image/png", "file1.png");
-        mDocsHelper.createDocument(rootDir0, "text/csv", "file2.csv");
-    }
-
-    public void testWindowTitle() throws Exception {
-        initTestFiles();
-
-        bots.main.assertWindowTitle(ROOT_0_ID);
-    }
-
-    public void testFilesListed() throws Exception {
-        initTestFiles();
-
-        bots.directory.assertDocumentsPresent("file0.log", "file1.png", "file2.csv");
-    }
-
-    public void testFilesList_LiveUpdate() throws Exception {
-        initTestFiles();
-
-        mDocsHelper.createDocument(rootDir0, "yummers/sandwich", "Ham & Cheese.sandwich");
-
-        bots.directory.waitForDocument("Ham & Cheese.sandwich");
-        bots.directory.assertDocumentsPresent(
-                "file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich");
-    }
-
-    public void testDeleteDocument() throws Exception {
-        initTestFiles();
-
-        bots.directory.clickDocument("file1.png");
-        device.waitForIdle();
-        bots.main.menuDelete().click();
-
-        bots.directory.waitForDeleteSnackbar();
-        bots.directory.assertDocumentsAbsent("file1.png");
-
-        bots.directory.waitForDeleteSnackbarGone();
-        bots.directory.assertDocumentsAbsent("file1.png");
-    }
-
-    public void testSupportsShare() throws Exception {
-        initTestFiles();
-
-        bots.directory.clickDocument("file1.png");
-        device.waitForIdle();
-        assertNotNull(bots.main.menuShare());
-    }
-
-    public void testClosesOnBack() throws Exception {
-        DownloadsActivity activity = getActivity();
-        device.pressBack();
-        device.wait(Until.gone(By.text(ROOT_0_ID)), TIMEOUT);  // wait for the window to go away
-        assertTrue(activity.isDestroyed());
-    }
-}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
index 2486209..e4afc3d 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
@@ -19,10 +19,17 @@
 import static com.android.documentsui.StubProvider.ROOT_0_ID;
 import static com.android.documentsui.StubProvider.ROOT_1_ID;
 
+import android.app.DownloadManager;
+import android.app.DownloadManager.Request;
+import android.content.Context;
+import android.net.Uri;
 import android.os.RemoteException;
+import android.support.test.uiautomator.Configurator;
+import android.support.test.uiautomator.UiObject;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.Suppress;
 import android.view.KeyEvent;
+import android.view.MotionEvent;
 
 import com.android.documentsui.model.RootInfo;
 
@@ -72,11 +79,11 @@
         bots.directory.assertDocumentsPresent("file0.log", "file1.png", "file2.csv");
     }
 
-    public void testLoadsHomeDirectoryByDefault() throws Exception {
+    public void testLoadsDownloadsDirectoryByDefault() throws Exception {
         initTestFiles();
 
         device.waitForIdle();
-        bots.main.assertWindowTitle("Documents");
+        bots.main.assertWindowTitle("Downloads");
     }
 
     public void testRootClickSetsWindowTitle() throws Exception {
@@ -173,4 +180,39 @@
             bots.roots.assertHasFocus();
         }
     }
+
+    // We don't really need to test the entirety of download support
+    // since downloads is (almost) just another provider.
+    @Suppress
+    public void testDownload_Queued() throws Exception {
+        DownloadManager dm = (DownloadManager) context.getSystemService(
+                Context.DOWNLOAD_SERVICE);
+        // This downloads ends up being queued (because DNS can't be resolved).
+        // We'll still see an entry in the downloads UI with a "Queued" label.
+        dm.enqueue(new Request(Uri.parse("http://hammychamp.toodles")));
+
+        bots.roots.openRoot("Downloads");
+        bots.directory.assertDocumentsPresent("Queued");
+    }
+
+    @Suppress
+    public void testDownload_RetryUnsuccessful() throws Exception {
+        DownloadManager dm = (DownloadManager) context.getSystemService(
+                Context.DOWNLOAD_SERVICE);
+        // This downloads fails! But it'll still show up.
+        dm.enqueue(new Request(Uri.parse("http://www.google.com/hamfancy")));
+
+        bots.roots.openRoot("Downloads");
+        UiObject doc = bots.directory.findDocument("Unsuccessful");
+        doc.waitForExists(TIMEOUT);
+
+        int toolType = Configurator.getInstance().getToolType();
+        Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_FINGER);
+        doc.click();
+        Configurator.getInstance().setToolType(toolType);
+
+        assertTrue(bots.main.findDownloadRetryDialog().exists());
+
+        device.pressBack(); // to clear the dialog.
+    }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
index 2527650..f71ce5d 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
@@ -518,28 +518,29 @@
         String rootId = extras.getString(EXTRA_PARENT_ID);
         String mimeType = extras.getString(Document.COLUMN_MIME_TYPE);
         String name = extras.getString(Document.COLUMN_DISPLAY_NAME);
+        List<String> streamTypes = extras.getStringArrayList(EXTRA_STREAM_TYPES);
         int flags = extras.getInt(EXTRA_FLAGS);
 
         Bundle out = new Bundle();
         String documentId = null;
         try {
-            documentId = createDocument(rootId, mimeType, name, flags);
+            documentId = createDocument(rootId, mimeType, name, flags, streamTypes);
             Uri uri = DocumentsContract.buildDocumentUri(mAuthority, documentId);
             out.putParcelable(DocumentsContract.EXTRA_URI, uri);
         } catch (FileNotFoundException e) {
-            Log.d(TAG, "Cretaing document with flags failed" + name);
+            Log.d(TAG, "Creating document with flags failed" + name);
         }
         return out;
     }
 
-    public String createDocument(String parentId, String mimeType, String displayName, int flags)
-            throws FileNotFoundException {
+    public String createDocument(String parentId, String mimeType, String displayName, int flags,
+            List<String> streamTypes) throws FileNotFoundException {
 
         StubDocument parent = mStorage.get(parentId);
         File file = createFile(parent, mimeType, displayName);
 
         final StubDocument document = StubDocument.createDocumentWithFlags(file, mimeType, parent,
-                flags);
+                flags, streamTypes);
         mStorage.put(document.documentId, document);
         Log.d(TAG, "Created document " + document.documentId);
         notifyParentChanged(document.parentId);
@@ -787,8 +788,9 @@
         }
 
         public static StubDocument createDocumentWithFlags(
-                File file, String mimeType, StubDocument parent, int flags) {
-            return new StubDocument(file, mimeType, new ArrayList<String>(), flags, parent);
+                File file, String mimeType, StubDocument parent, int flags,
+                List<String> streamTypes) {
+            return new StubDocument(file, mimeType, streamTypes, flags, parent);
         }
 
         public static StubDocument createVirtualDocument(
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java
index 11f5194..5b53caf 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/bots/UiBot.java
@@ -173,6 +173,13 @@
         return findObject("android:id/content", "android:id/text1");
     }
 
+    public UiObject findDownloadRetryDialog() {
+        UiSelector selector = new UiSelector().text("Couldn't download");
+        UiObject title = mDevice.findObject(selector);
+        title.waitForExists(mTimeout);
+        return title;
+    }
+
     public UiObject findDialogOkButton() {
         UiObject object = findObject("android:id/content", "android:id/button1");
         object.waitForExists(mTimeout);
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java
index adc8141..7ab51ba2 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java
@@ -68,8 +68,8 @@
 
     // Tests that the item count is correct.
     public void testHide_ItemCount() {
-        List<String> ids = mModel.getModelIds();
-        mAdapter.hide(ids.get(0), ids.get(1));
+        String[] ids = mModel.getModelIds();
+        mAdapter.hide(ids[0], ids[1]);
         assertEquals(mModel.getItemCount() - 2, mAdapter.getItemCount());
     }
 
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
index 4b0bc41..c6ad511 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
@@ -107,7 +107,7 @@
 
         assertTrue(model.isEmpty());
         assertEquals(0, model.getItemCount());
-        assertEquals(0, model.getModelIds().size());
+        assertEquals(0, model.getModelIds().length);
     }
 
     // Tests that the item count is correct.
@@ -165,10 +165,10 @@
 
     // Tests the base case for Model.getItem.
     public void testGetItem() {
-        List<String> ids = model.getModelIds();
-        assertEquals(ITEM_COUNT, ids.size());
+        String[] ids = model.getModelIds();
+        assertEquals(ITEM_COUNT, ids.length);
         for (int i = 0; i < ITEM_COUNT; ++i) {
-            Cursor c = model.getItem(ids.get(i));
+            Cursor c = model.getItem(ids[i]);
             assertEquals(i, c.getPosition());
         }
     }
@@ -292,14 +292,14 @@
         r.sortOrder = State.SORT_ORDER_LAST_MODIFIED;
         model.update(r);
 
-        List<String> ids = model.getModelIds();
+        String[] ids = model.getModelIds();
 
         // Check that all items were accounted for
-        assertEquals(ITEM_COUNT + DL_COUNT, ids.size());
+        assertEquals(ITEM_COUNT + DL_COUNT, ids.length);
 
         // Check that active downloads are sorted to the top.
         for (int i = 0; i < DL_COUNT; i++) {
-            assertTrue(currentDownloads.contains(ids.get(i)));
+            assertTrue(currentDownloads.contains(ids[i]));
         }
     }
 
@@ -316,11 +316,11 @@
     }
 
     private Selection positionToSelection(int... positions) {
-        List<String> ids = model.getModelIds();
+        String[] ids = model.getModelIds();
         Selection s = new Selection();
         // Construct a selection of the given positions.
         for (int p: positions) {
-            s.add(ids.get(p));
+            s.add(ids[p]);
         }
         return s;
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
index 353d4bd..0c0e0b7 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
@@ -27,6 +27,7 @@
 import com.android.documentsui.dirlist.MultiSelectManager.GridModel;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Set;
 
 @SmallTest
@@ -42,6 +43,17 @@
     private Set<String> lastSelection;
     private int viewWidth;
 
+    // TLDR: Don't call model.{start|resize}Selection; use the local #startSelection and
+    // #resizeSelection methods instead.
+    //
+    // The reason for this is that selection is stateful and involves operations that take the
+    // current UI state (e.g scrolling) into account. This test maintains its own copy of the
+    // selection bounds as control data for verifying selections. Keep this data in sync by calling
+    // #startSelection and
+    // #resizeSelection.
+    private Point mSelectionOrigin;
+    private Point mSelectionPoint;
+
     private void initData(final int numChildren, int numColumns) {
         env = new TestEnvironment(numChildren, numColumns);
         adapter = new TestDocumentsAdapter(new ArrayList<String>()) {
@@ -76,139 +88,241 @@
 
     public void testSelectionLeftOfItems() {
         initData(20, 5);
-        model.startSelection(new Point(0, 10));
-        model.resizeSelection(new Point(1, 11));
-        assertSelected();
+        startSelection(new Point(0, 10));
+        resizeSelection(new Point(1, 11));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testSelectionRightOfItems() {
         initData(20, 4);
-        model.startSelection(new Point(viewWidth - 1, 10));
-        model.resizeSelection(new Point(viewWidth - 2, 11));
-        assertSelected();
+        startSelection(new Point(viewWidth - 1, 10));
+        resizeSelection(new Point(viewWidth - 2, 11));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testSelectionAboveItems() {
         initData(20, 4);
-        model.startSelection(new Point(10, 0));
-        model.resizeSelection(new Point(11, 1));
-        assertSelected();
+        startSelection(new Point(10, 0));
+        resizeSelection(new Point(11, 1));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testSelectionBelowItems() {
         initData(5, 4);
-        model.startSelection(new Point(10, VIEWPORT_HEIGHT - 1));
-        model.resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2));
-        assertSelected();
+        startSelection(new Point(10, VIEWPORT_HEIGHT - 1));
+        resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testVerticalSelectionBetweenItems() {
         initData(20, 4);
-        model.startSelection(new Point(106, 0));
-        model.resizeSelection(new Point(107, 200));
-        assertSelected();
+        startSelection(new Point(106, 0));
+        resizeSelection(new Point(107, 200));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testHorizontalSelectionBetweenItems() {
         initData(20, 4);
-        model.startSelection(new Point(0, 105));
-        model.resizeSelection(new Point(200, 106));
-        assertSelected();
+        startSelection(new Point(0, 105));
+        resizeSelection(new Point(200, 106));
+        assertNoSelection();
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testGrowingAndShrinkingSelection() {
         initData(20, 4);
-        model.startSelection(new Point(0, 0));
-        model.resizeSelection(new Point(5, 5));
-        assertSelected(0);
-        model.resizeSelection(new Point(109, 109));
-        assertSelected(0);
-        model.resizeSelection(new Point(110, 109));
-        assertSelected(0, 1);
-        model.resizeSelection(new Point(110, 110));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(214, 214));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(215, 214));
-        assertSelected(0, 1, 2, 4, 5, 6);
-        model.resizeSelection(new Point(214, 214));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(110, 110));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(110, 109));
-        assertSelected(0, 1);
-        model.resizeSelection(new Point(109, 109));
-        assertSelected(0);
-        model.resizeSelection(new Point(5, 5));
-        assertSelected(0);
-        model.resizeSelection(new Point(0, 0));
-        assertSelected();
+        startSelection(new Point(0, 0));
+
+        resizeSelection(new Point(5, 5));
+        verifySelection();
+
+        resizeSelection(new Point(109, 109));
+        verifySelection();
+
+        resizeSelection(new Point(110, 109));
+        verifySelection();
+
+        resizeSelection(new Point(110, 110));
+        verifySelection();
+
+        resizeSelection(new Point(214, 214));
+        verifySelection();
+
+        resizeSelection(new Point(215, 214));
+        verifySelection();
+
+        resizeSelection(new Point(214, 214));
+        verifySelection();
+
+        resizeSelection(new Point(110, 110));
+        verifySelection();
+
+        resizeSelection(new Point(110, 109));
+        verifySelection();
+
+        resizeSelection(new Point(109, 109));
+        verifySelection();
+
+        resizeSelection(new Point(5, 5));
+        verifySelection();
+
+        resizeSelection(new Point(0, 0));
+        verifySelection();
+
         assertEquals(NOT_SET, model.getPositionNearestOrigin());
     }
 
     public void testSelectionMovingAroundOrigin() {
         initData(16, 4);
-        model.startSelection(new Point(210, 210));
-        model.resizeSelection(new Point(viewWidth - 1, 0));
-        assertSelected(2, 3, 6, 7);
-        model.resizeSelection(new Point(0, 0));
-        assertSelected(0, 1, 4, 5);
-        model.resizeSelection(new Point(0, 420));
-        assertSelected(8, 9, 12, 13);
-        model.resizeSelection(new Point(viewWidth - 1, 420));
-        assertSelected(10, 11, 14, 15);
-        assertEquals(10, model.getPositionNearestOrigin());
+
+        startSelection(new Point(210, 210));
+        resizeSelection(new Point(viewWidth - 1, 0));
+        verifySelection();
+
+        resizeSelection(new Point(0, 0));
+        verifySelection();
+
+        resizeSelection(new Point(0, 420));
+        verifySelection();
+
+        resizeSelection(new Point(viewWidth - 1, 420));
+        verifySelection();
+
+        // This is manually figured and will need to be adjusted if the separator position is
+        // changed.
+        assertEquals(7, model.getPositionNearestOrigin());
     }
 
     public void testScrollingBandSelect() {
         initData(40, 4);
-        model.startSelection(new Point(0, 0));
-        model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
-        assertSelected(0, 4, 8, 12, 16);
+
+        startSelection(new Point(0, 0));
+        resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
+        verifySelection();
+
         scroll(CHILD_VIEW_EDGE_PX);
-        assertSelected(0, 4, 8, 12, 16, 20);
-        model.resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1));
-        assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21);
+        verifySelection();
+
+        resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1));
+        verifySelection();
+
         scroll(CHILD_VIEW_EDGE_PX);
-        assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21, 24, 25);
+        verifySelection();
+
         scroll(-2 * CHILD_VIEW_EDGE_PX);
-        assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17);
-        model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
-        assertSelected(0, 4, 8, 12, 16);
+        verifySelection();
+
+        resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
+        verifySelection();
+
         assertEquals(0, model.getPositionNearestOrigin());
     }
 
-    private void assertSelected(int... selectedPositions) {
-        assertEquals(selectedPositions.length, lastSelection.size());
-        for (int position : selectedPositions) {
-            assertTrue(lastSelection.contains(Integer.toString(position)));
+    /** Returns the current selection area as a Rect. */
+    private Rect getSelectionArea() {
+        // Construct a rect from the two selection points.
+        Rect selectionArea = new Rect(
+                mSelectionOrigin.x, mSelectionOrigin.y, mSelectionOrigin.x, mSelectionOrigin.y);
+        selectionArea.union(mSelectionPoint.x, mSelectionPoint.y);
+        // Rect intersection tests are exclusive of bounds, while the MSM's selection code is
+        // inclusive. Expand the rect by 1 pixel in all directions to account for this.
+        selectionArea.inset(-1, -1);
+
+        return selectionArea;
+    }
+
+    /** Asserts that the selection is currently empty. */
+    private void assertNoSelection() {
+        assertEquals("Unexpected items " + lastSelection + " in selection " + getSelectionArea(),
+                0, lastSelection.size());
+    }
+
+    /** Verifies the selection using actual bbox checks. */
+    private void verifySelection() {
+        Rect selectionArea = getSelectionArea();
+        for (TestEnvironment.Item item: env.items) {
+            if (Rect.intersects(selectionArea, item.rect)) {
+                assertTrue("Expected item " + item + " was not in selection " + selectionArea,
+                        lastSelection.contains(item.name));
+            } else {
+                assertFalse("Unexpected item " + item + " in selection" + selectionArea,
+                        lastSelection.contains(item.name));
+            }
         }
     }
 
+    private void startSelection(Point p) {
+        model.startSelection(p);
+        mSelectionOrigin = env.createAbsolutePoint(p);
+    }
+
+    private void resizeSelection(Point p) {
+        model.resizeSelection(p);
+        mSelectionPoint = env.createAbsolutePoint(p);
+    }
+
     private void scroll(int dy) {
         assertTrue(env.verticalOffset + VIEWPORT_HEIGHT + dy <= env.getTotalHeight());
         env.verticalOffset += dy;
+        // Correct the cached selection point as well.
+        mSelectionPoint.y += dy;
         model.onScrolled(null, 0, dy);
     }
 
     private static final class TestEnvironment implements MultiSelectManager.SelectionEnvironment {
 
-        public int horizontalOffset = 0;
-        public int verticalOffset = 0;
         private final int mNumColumns;
         private final int mNumRows;
         private final int mNumChildren;
+        private final int mSeparatorPosition;
+
+        public int horizontalOffset = 0;
+        public int verticalOffset = 0;
+        private List<Item> items = new ArrayList<>();
 
         public TestEnvironment(int numChildren, int numColumns) {
             mNumChildren = numChildren;
             mNumColumns = numColumns;
-            mNumRows = (int) Math.ceil((double) numChildren / mNumColumns);
+            mSeparatorPosition = mNumColumns + 1;
+            mNumRows = setupGrid();
+        }
+
+        private int setupGrid() {
+            // Split the input set into folders and documents. Do this such that there is a
+            // partially-populated row in the middle of the grid, to test corner cases in layout
+            // code.
+            int y = VIEW_PADDING_PX;
+            int i = 0;
+            int numRows = 0;
+            while (i < mNumChildren) {
+                int top = y;
+                int height = CHILD_VIEW_EDGE_PX;
+                int width = CHILD_VIEW_EDGE_PX;
+                for (int j = 0; j < mNumColumns && i < mNumChildren; j++) {
+                    int left = VIEW_PADDING_PX + (j * (width + VIEW_PADDING_PX));
+                    items.add(new Item(
+                            Integer.toString(i),
+                            new Rect(
+                                    left,
+                                    top,
+                                    left + width - 1,
+                                    top + height - 1)));
+
+                    // Create a partially populated row at the separator position.
+                    if (++i == mSeparatorPosition) {
+                        break;
+                    }
+                }
+                y += height + VIEW_PADDING_PX;
+                numRows++;
+            }
+
+            return numRows;
         }
 
         private int getTotalHeight() {
@@ -227,8 +341,16 @@
 
         private int getNumItemsInRow(int index) {
             assertTrue(index >= 0 && index < mNumRows);
-            if (index == mNumRows - 1 && mNumChildren % mNumColumns != 0) {
-                return mNumChildren % mNumColumns;
+            int mod = mSeparatorPosition % mNumColumns;
+            if (index == (mSeparatorPosition / mNumColumns)) {
+                // The row containing the separator may be incomplete
+                return mod > 0 ? mod : mNumColumns;
+            }
+            // Account for the partial separator row in the final row tally.
+            if (index == mNumRows - 1) {
+                // The last row may be incomplete
+                int finalRowCount = (mNumChildren - mod) % mNumColumns;
+                return finalRowCount > 0 ? finalRowCount : mNumColumns;
             }
 
             return mNumColumns;
@@ -257,21 +379,18 @@
 
         @Override
         public int getAdapterPositionAt(int index) {
-            return index + mNumColumns * (getFirstVisibleRowIndex());
+            // Account for partial rows by actually tallying up the items in hidden rows.
+            int hiddenCount = 0;
+            for (int i = 0; i < getFirstVisibleRowIndex(); i++) {
+                hiddenCount += getNumItemsInRow(i);
+            }
+            return index + hiddenCount;
         }
 
         @Override
         public Rect getAbsoluteRectForChildViewAt(int index) {
-            int adapterPosition = (getFirstVisibleRowIndex() * mNumColumns) + index;
-            int rowIndex = adapterPosition / mNumColumns;
-            int columnIndex = adapterPosition % mNumColumns;
-
-            Rect rect = new Rect();
-            rect.top = VIEW_PADDING_PX + rowIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
-            rect.bottom = rect.top + CHILD_VIEW_EDGE_PX - 1;
-            rect.left = VIEW_PADDING_PX + columnIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX);
-            rect.right = rect.left + CHILD_VIEW_EDGE_PX - 1;
-            return rect;
+            int adapterPosition = getAdapterPositionAt(index);
+            return items.get(adapterPosition).rect;
         }
 
         @Override
@@ -285,11 +404,6 @@
         }
 
         @Override
-        public int getRowCount() {
-            return mNumRows;
-        }
-
-        @Override
         public void showBand(Rect rect) {
             throw new UnsupportedOperationException();
         }
@@ -328,5 +442,19 @@
         public boolean isLayoutItem(int adapterPosition) {
             return false;
         }
+
+        public static final class Item {
+            public String name;
+            public Rect rect;
+
+            public Item(String n, Rect r) {
+                name = n;
+                rect = r;
+            }
+
+            public String toString() {
+                return name + ": " + rect;
+            }
+        }
     }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
index 8e624a0..56e54a6 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
@@ -87,11 +87,6 @@
     }
 
     @Override
-    public int getRowCount() {
-        return 0;
-    }
-
-    @Override
     public int getChildCount() {
         return 0;
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/services/CopyJobTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/services/CopyJobTest.java
index 543396e..bb7c01a 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/services/CopyJobTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/services/CopyJobTest.java
@@ -16,6 +16,10 @@
 
 package com.android.documentsui.services;
 
+import static com.google.common.collect.Lists.newArrayList;
+
+import android.net.Uri;
+import android.provider.DocumentsContract.Document;
 import android.test.suitebuilder.annotation.MediumTest;
 
 import com.android.documentsui.model.DocumentInfo;
@@ -38,6 +42,21 @@
         runCopyVirtualNonTypedFileTest();
     }
 
+    public void testCopy_BackendSideVirtualTypedFile_Fallback() throws Exception {
+        mDocs.assertChildCount(mDestRoot, 0);
+
+        Uri testFile = mDocs.createDocumentWithFlags(
+                mSrcRoot.documentId, "virtual/mime-type", "tokyo.sth",
+                Document.FLAG_VIRTUAL_DOCUMENT | Document.FLAG_SUPPORTS_COPY
+                        | Document.FLAG_SUPPORTS_MOVE, "application/pdf");
+
+        createJob(newArrayList(testFile)).run();
+
+        mJobListener.waitForFinished();
+        mDocs.assertChildCount(mDestRoot, 1);
+        mDocs.assertHasFile(mDestRoot, "tokyo.sth.pdf");  // Copy should convert file to PDF.
+    }
+
     public void testCopyEmptyDir() throws Exception {
         runCopyEmptyDirTest();
     }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/services/MoveJobTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/services/MoveJobTest.java
index 749264a..24181d6 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/services/MoveJobTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/services/MoveJobTest.java
@@ -59,6 +59,21 @@
         mDocs.assertChildCount(mSrcRoot, 1);
     }
 
+    public void testMove_BackendSideVirtualTypedFile_Fallback() throws Exception {
+        Uri testFile = mDocs.createDocumentWithFlags(
+                mSrcRoot.documentId, "virtual/mime-type", "tokyo.sth",
+                Document.FLAG_VIRTUAL_DOCUMENT | Document.FLAG_SUPPORTS_COPY
+                        | Document.FLAG_SUPPORTS_MOVE, "application/pdf");
+
+        createJob(newArrayList(testFile)).run();
+        mJobListener.waitForFinished();
+
+        // Should have failed, source not deleted. Moving by bytes for virtual files
+        // is not supported.
+        mDocs.assertChildCount(mDestRoot, 0);
+        mDocs.assertChildCount(mSrcRoot, 1);
+    }
+
     public void testMoveEmptyDir() throws Exception {
         runCopyEmptyDirTest();
 
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java b/packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java
similarity index 83%
rename from packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
rename to packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java
index 55f55b0..83488cd 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.mtp.exceptions;
+package com.android.mtp;
 
 import java.io.IOException;
 
 /**
  * Exception thrown when the device is busy and the requested operation cannon be completed.
  */
-public class BusyDeviceException extends IOException {
+class BusyDeviceException extends IOException {
+    BusyDeviceException() {
+        super("The MTP device is busy.");
+    }
 }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
index 72ad2f6..8c73211 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
@@ -830,11 +830,21 @@
         if (info.getFormat() == MtpConstants.FORMAT_ASSOCIATION) {
             return DocumentsContract.Document.MIME_TYPE_DIR;
         }
+
         final String formatCodeMimeType = MediaFile.getMimeTypeForFormatCode(info.getFormat());
+        final String mediaFileMimeType = MediaFile.getMimeTypeForFile(info.getName());
+
+        // Format code can be mapped with multiple mime types, e.g. FORMAT_MPEG is mapped with
+        // audio/mp4 and video/mp4.
+        // As file extension contains more information than format code, returns mime type obtained
+        // from file extension if it is consistent with format code.
+        if (mediaFileMimeType != null &&
+                MediaFile.getFormatCode("", mediaFileMimeType) == info.getFormat()) {
+            return mediaFileMimeType;
+        }
         if (formatCodeMimeType != null) {
             return formatCodeMimeType;
         }
-        final String mediaFileMimeType = MediaFile.getMimeTypeForFile(info.getName());
         if (mediaFileMimeType != null) {
             return mediaFileMimeType;
         }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index d4d4591..68c1992 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -22,6 +22,7 @@
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.MatrixCursor;
+import android.database.sqlite.SQLiteDiskIOException;
 import android.graphics.Point;
 import android.media.MediaFile;
 import android.mtp.MtpConstants;
@@ -29,6 +30,8 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.CancellationSignal;
+import android.os.FileUriExposedException;
+import android.os.FileUtils;
 import android.os.ParcelFileDescriptor;
 import android.os.storage.StorageManager;
 import android.provider.DocumentsContract.Document;
@@ -36,18 +39,17 @@
 import android.provider.DocumentsContract;
 import android.provider.DocumentsProvider;
 import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.mtp.exceptions.BusyDeviceException;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeoutException;
 
 /**
  * DocumentsProvider for MTP devices.
@@ -103,25 +105,33 @@
 
         // Check boot count and cleans database if it's first time to launch MtpDocumentsProvider
         // after booting.
-        final int bootCount = Settings.Global.getInt(mResolver, Settings.Global.BOOT_COUNT, -1);
-        final int lastBootCount = mDatabase.getLastBootCount();
-        if (bootCount != -1 && bootCount != lastBootCount) {
-            mDatabase.setLastBootCount(bootCount);
-            final List<UriPermission> permissions = mResolver.getOutgoingPersistedUriPermissions();
-            final Uri[] uris = new Uri[permissions.size()];
-            for (int i = 0; i < permissions.size(); i++) {
-                uris[i] = permissions.get(i).getUri();
+        try {
+            final int bootCount = Settings.Global.getInt(mResolver, Settings.Global.BOOT_COUNT, -1);
+            final int lastBootCount = mDatabase.getLastBootCount();
+            if (bootCount != -1 && bootCount != lastBootCount) {
+                mDatabase.setLastBootCount(bootCount);
+                final List<UriPermission> permissions =
+                        mResolver.getOutgoingPersistedUriPermissions();
+                final Uri[] uris = new Uri[permissions.size()];
+                for (int i = 0; i < permissions.size(); i++) {
+                    uris[i] = permissions.get(i).getUri();
+                }
+                mDatabase.cleanDatabase(uris);
             }
-            mDatabase.cleanDatabase(uris);
+        } catch (SQLiteDiskIOException error) {
+            // It can happen due to disk shortage.
+            Log.e(TAG, "Failed to clean database.", error);
+            return false;
         }
 
         // TODO: Mount AppFuse on demands.
         try {
             mAppFuse.mount(getContext().getSystemService(StorageManager.class));
-        } catch (IOException e) {
-            Log.e(TAG, "Failed to start app fuse.", e);
+        } catch (IOException error) {
+            Log.e(TAG, "Failed to start app fuse.", error);
             return false;
         }
+
         resume();
         return true;
     }
@@ -315,25 +325,61 @@
         if (DEBUG) {
             Log.d(TAG, "createDocument: " + displayName);
         }
+        final Identifier parentId;
+        final MtpDeviceRecord record;
+        final ParcelFileDescriptor[] pipe;
         try {
-            final Identifier parentId = mDatabase.createIdentifier(parentDocumentId);
+            parentId = mDatabase.createIdentifier(parentDocumentId);
             openDevice(parentId.mDeviceId);
-            final MtpDeviceRecord record = getDeviceToolkit(parentId.mDeviceId).mDeviceRecord;
+            record = getDeviceToolkit(parentId.mDeviceId).mDeviceRecord;
             if (!MtpDeviceRecord.isWritingSupported(record.operationsSupported)) {
-                throw new UnsupportedOperationException();
+                throw new UnsupportedOperationException(
+                        "Writing operation is not supported by the device.");
             }
-            final ParcelFileDescriptor pipe[] = ParcelFileDescriptor.createReliablePipe();
-            pipe[0].close();  // 0 bytes for a new document.
-            final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ?
-                    MtpConstants.FORMAT_ASSOCIATION :
-                    MediaFile.getFormatCode(displayName, mimeType);
-            final MtpObjectInfo info = new MtpObjectInfo.Builder()
-                    .setStorageId(parentId.mStorageId)
-                    .setParent(parentId.mObjectHandle)
-                    .setFormat(formatCode)
-                    .setName(displayName)
-                    .build();
-            final int objectHandle = mMtpManager.createDocument(parentId.mDeviceId, info, pipe[1]);
+            pipe = ParcelFileDescriptor.createReliablePipe();
+            int objectHandle = -1;
+            MtpObjectInfo info = null;
+            try {
+                pipe[0].close();  // 0 bytes for a new document.
+
+                final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ?
+                        MtpConstants.FORMAT_ASSOCIATION :
+                        MediaFile.getFormatCode(displayName, mimeType);
+                info = new MtpObjectInfo.Builder()
+                        .setStorageId(parentId.mStorageId)
+                        .setParent(parentId.mObjectHandle)
+                        .setFormat(formatCode)
+                        .setName(displayName)
+                        .build();
+
+                final String[] parts = FileUtils.splitFileName(mimeType, displayName);
+                final String baseName = parts[0];
+                final String extension = parts[1];
+                for (int i = 0; i <= 32; i++) {
+                    final MtpObjectInfo infoUniqueName;
+                    if (i == 0) {
+                        infoUniqueName = info;
+                    } else {
+                        infoUniqueName = new MtpObjectInfo.Builder(info).setName(
+                                baseName + " (" + i + ")." + extension).build();
+                    }
+                    try {
+                        objectHandle = mMtpManager.createDocument(
+                                parentId.mDeviceId, infoUniqueName, pipe[1]);
+                        break;
+                    } catch (SendObjectInfoFailure exp) {
+                        // This can be caused when we have an existing file with the same name.
+                        continue;
+                    }
+                }
+            } finally {
+                pipe[1].close();
+            }
+            if (objectHandle == -1) {
+                throw new IllegalArgumentException(
+                        "The file name \"" + displayName + "\" is conflicted with existing files " +
+                        "and the provider failed to find unique name.");
+            }
             final MtpObjectInfo infoWithHandle =
                     new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build();
             final String documentId = mDatabase.putNewDocument(
@@ -342,9 +388,12 @@
             getDocumentLoader(parentId).clearTask(parentId);
             notifyChildDocumentsChange(parentDocumentId);
             return documentId;
+        } catch (FileNotFoundException | RuntimeException error) {
+            Log.e(TAG, "createDocument", error);
+            throw error;
         } catch (IOException error) {
             Log.e(TAG, "createDocument", error);
-            throw new FileNotFoundException(error.getMessage());
+            throw new IllegalStateException(error);
         }
     }
 
@@ -426,7 +475,7 @@
                     closeDeviceInternal(id);
                 }
                 mRootScanner.pause();
-            } catch (InterruptedException|IOException e) {
+            } catch (InterruptedException | IOException | TimeoutException e) {
                 // It should fail unit tests by throwing runtime exception.
                 throw new RuntimeException(e);
             } finally {
@@ -464,9 +513,6 @@
         getDeviceToolkit(deviceId).close();
         mDeviceToolkits.remove(deviceId);
         mMtpManager.closeDevice(deviceId);
-        if (mDeviceToolkits.size() == 0) {
-            mRootScanner.pause();
-        }
     }
 
     private DeviceToolkit getDeviceToolkit(int deviceId) throws FileNotFoundException {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 0202343..6fb2a78 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -33,7 +33,6 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.mtp.exceptions.BusyDeviceException;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -190,7 +189,7 @@
         synchronized (device) {
             final MtpObjectInfo sendObjectInfoResult = device.sendObjectInfo(objectInfo);
             if (sendObjectInfoResult == null) {
-                throw new IOException("Failed to create a document");
+                throw new SendObjectInfoFailure();
             }
             if (objectInfo.getFormat() != MtpConstants.FORMAT_ASSOCIATION) {
                 if (!device.sendObject(sendObjectInfoResult.getObjectHandle(),
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
index 2f66c5c..2e9133b 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java
@@ -27,6 +27,7 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 final class RootScanner {
     /**
@@ -95,15 +96,19 @@
      * Stops background thread and wait for its termination.
      * @throws InterruptedException
      */
-    synchronized void pause() throws InterruptedException {
+    synchronized void pause() throws InterruptedException, TimeoutException {
         if (mExecutor == null) {
             return;
         }
         mExecutor.shutdownNow();
-        if (!mExecutor.awaitTermination(AWAIT_TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS)) {
-            Log.e(MtpDocumentsProvider.TAG, "Failed to terminate RootScanner's background thread.");
+        try {
+            if (!mExecutor.awaitTermination(AWAIT_TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS)) {
+                throw new TimeoutException(
+                        "Timeout for terminating RootScanner's background thread.");
+            }
+        } finally {
+            mExecutor = null;
         }
-        mExecutor = null;
     }
 
     /**
@@ -173,6 +178,9 @@
                 }
                 mFirstScanCompleted.countDown();
                 pollingCount++;
+                if (devices.length == 0) {
+                    break;
+                }
                 try {
                     // Use SHORT_POLLING_PERIOD for the first SHORT_POLLING_TIMES because it is
                     // more likely to add new root just after the device is added.
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java b/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java
similarity index 75%
copy from packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
copy to packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java
index 55f55b0..db7d777 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.mtp.exceptions;
+package com.android.mtp;
 
 import java.io.IOException;
 
 /**
- * Exception thrown when the device is busy and the requested operation cannon be completed.
+ * Exception thrown when sendObjectInfo failed.
  */
-public class BusyDeviceException extends IOException {
+class SendObjectInfoFailure extends IOException {
+    SendObjectInfoFailure() {
+        super("Failed to MtpDevice#sendObjectInfo.");
+    }
 }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
index e49a935..b74069a 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
@@ -17,6 +17,8 @@
 package com.android.mtp;
 
 import android.database.Cursor;
+import android.media.MediaFile;
+import android.media.MediaFile.MediaFileType;
 import android.mtp.MtpConstants;
 import android.mtp.MtpObjectInfo;
 import android.net.Uri;
@@ -1081,6 +1083,43 @@
         }
     }
 
+    public void testFormatCodeForMpeg() throws FileNotFoundException {
+        addTestDevice();
+        addTestStorage("1");
+        mDatabase.getMapper().startAddingDocuments("2");
+        mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] {
+            createDocument(100, "audio.m4a", MtpConstants.FORMAT_MPEG, 1000),
+            createDocument(101, "video.m4v", MtpConstants.FORMAT_MPEG, 1000),
+            createDocument(102, "unknown.mp4", MtpConstants.FORMAT_MPEG, 1000),
+            createDocument(103, "inconsistent.txt", MtpConstants.FORMAT_MPEG, 1000),
+            createDocument(104, "noext", MtpConstants.FORMAT_UNDEFINED, 1000),
+        });
+        mDatabase.getMapper().stopAddingDocuments("2");
+        try (final Cursor cursor = mDatabase.queryChildDocuments(
+                strings(COLUMN_DISPLAY_NAME,  COLUMN_MIME_TYPE),
+                "2")) {
+            assertEquals(5, cursor.getCount());
+            cursor.moveToNext();
+            assertEquals("audio.m4a", cursor.getString(0));
+            assertEquals("audio/mp4", cursor.getString(1));
+            cursor.moveToNext();
+            assertEquals("video.m4v", cursor.getString(0));
+            assertEquals("video/mp4", cursor.getString(1));
+            cursor.moveToNext();
+            // Assume that the file is video as we don't have any hints to find out if the file is
+            // video or audio.
+            assertEquals("unknown.mp4", cursor.getString(0));
+            assertEquals("video/mp4", cursor.getString(1));
+            // Don't return mime type that is inconsistent with format code.
+            cursor.moveToNext();
+            assertEquals("inconsistent.txt", cursor.getString(0));
+            assertEquals("video/mp4", cursor.getString(1));
+            cursor.moveToNext();
+            assertEquals("noext", cursor.getString(0));
+            assertEquals("application/octet-stream", cursor.getString(1));
+        }
+    }
+
     private void addTestDevice() throws FileNotFoundException {
         TestUtil.addTestDevice(mDatabase);
     }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index d6ad0f3..9c1880a 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -30,8 +30,6 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
 
-import com.android.mtp.exceptions.BusyDeviceException;
-
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.Arrays;
@@ -262,11 +260,9 @@
                 null));
         {
             mProvider.openDevice(0);
-            mProvider.resumeRootScanner();
             mResolver.waitForNotification(ROOTS_URI, 1);
 
             mProvider.openDevice(1);
-            mProvider.resumeRootScanner();
             mResolver.waitForNotification(ROOTS_URI, 2);
 
             final Cursor cursor = mProvider.queryRoots(null);
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
index cdddd81..a08d9ee 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
@@ -48,6 +48,7 @@
     @Override
     protected void tearDown() throws Exception {
         assertTrue(mPipeManager.close());
+        mDatabase.close();
     }
 
     public void testReadDocument_basic() throws Exception {
diff --git a/packages/PrintSpooler/res/values-es/strings.xml b/packages/PrintSpooler/res/values-es/strings.xml
index a0ce57a..dba0491 100644
--- a/packages/PrintSpooler/res/values-es/strings.xml
+++ b/packages/PrintSpooler/res/values-es/strings.xml
@@ -66,8 +66,8 @@
     <string name="print_no_print_services" msgid="8561247706423327966">"No hay servicios de impresión habilitados"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"No se encontraron impresoras"</string>
     <string name="cannot_add_printer" msgid="7840348733668023106">"No se pueden añadir impresoras"</string>
-    <string name="select_to_add_printers" msgid="3800709038689830974">"Seleccionar para añadir una impresora"</string>
-    <string name="enable_print_service" msgid="3482815747043533842">"Seleccionar para habilitar"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"Selecciona para añadir una impresora"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"Selecciona para habilitar"</string>
     <string name="enabled_services_title" msgid="7036986099096582296">"Servicios habilitados"</string>
     <string name="recommended_services_title" msgid="3799434882937956924">"Servicios recomendados"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"Servicios inhabilitados"</string>
diff --git a/packages/PrintSpooler/res/values-ne-rNP/strings.xml b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
index e12c8df..5af3a04 100644
--- a/packages/PrintSpooler/res/values-ne-rNP/strings.xml
+++ b/packages/PrintSpooler/res/values-ne-rNP/strings.xml
@@ -68,7 +68,7 @@
     <string name="cannot_add_printer" msgid="7840348733668023106">"प्रिन्टरहरू थप्न सक्दैन"</string>
     <string name="select_to_add_printers" msgid="3800709038689830974">"प्रिन्टर थप्नका लागि चयन गर्नुहोस्"</string>
     <string name="enable_print_service" msgid="3482815747043533842">"सक्षम गर्नका लागि चयन गर्नुहोस्"</string>
-    <string name="enabled_services_title" msgid="7036986099096582296">"सेवाहरूलाई सक्षम गर्नुहोस्"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"सक्षम गरिएका सेवाहरू"</string>
     <string name="recommended_services_title" msgid="3799434882937956924">"सिफारिस गरिएका सेवाहरू"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"असक्षम गरिएका सेवाहरू"</string>
     <string name="all_services_title" msgid="5578662754874906455">"सबै सेवाहरू"</string>
diff --git a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
index ee6266f..a6af5bd 100644
--- a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
+++ b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml
@@ -61,7 +61,7 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"Printer haqida batafsil ma’lumot"</string>
-    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Bir qancha chop etish xizmatlari o‘chirilgan"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"Ayrim chop etish xizmatlari o‘chirib qo‘yilgan"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"Printerlar qidirilmoqda"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"Hech qaysi chop etish xizmati yoqilmagan"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"Printerlar topilmadi"</string>
@@ -70,7 +70,7 @@
     <string name="enable_print_service" msgid="3482815747043533842">"Yoqish uchun tanlang"</string>
     <string name="enabled_services_title" msgid="7036986099096582296">"Yoqilgan xizmatlar"</string>
     <string name="recommended_services_title" msgid="3799434882937956924">"Tavsiya etilgan xizmatlar"</string>
-    <string name="disabled_services_title" msgid="7313253167968363211">"O‘chirilgan xizmatlar"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"O‘chirib qo‘yilgan xizmatlar"</string>
     <string name="all_services_title" msgid="5578662754874906455">"Barcha xizmatlar"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Chop etilmoqda: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> bekor qilinmoqda"</string>
diff --git a/packages/PrintSpooler/res/values-zh-rCN/strings.xml b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
index 4a27839..fb30e44 100644
--- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
@@ -61,25 +61,17 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"关于此打印机的更多信息"</string>
-    <!-- no translation found for print_services_disabled_toast (9089060734685174685) -->
-    <skip />
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"部分打印服务已停用"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"正在搜索打印机"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"未启用任何打印服务"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"找不到打印机"</string>
-    <!-- no translation found for cannot_add_printer (7840348733668023106) -->
-    <skip />
-    <!-- no translation found for select_to_add_printers (3800709038689830974) -->
-    <skip />
-    <!-- no translation found for enable_print_service (3482815747043533842) -->
-    <skip />
-    <!-- no translation found for enabled_services_title (7036986099096582296) -->
-    <skip />
-    <!-- no translation found for recommended_services_title (3799434882937956924) -->
-    <skip />
-    <!-- no translation found for disabled_services_title (7313253167968363211) -->
-    <skip />
-    <!-- no translation found for all_services_title (5578662754874906455) -->
-    <skip />
+    <string name="cannot_add_printer" msgid="7840348733668023106">"无法添加打印机"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"选择即可添加打印机"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"选择即可启用"</string>
+    <string name="enabled_services_title" msgid="7036986099096582296">"已启用的服务"</string>
+    <string name="recommended_services_title" msgid="3799434882937956924">"推荐的服务"</string>
+    <string name="disabled_services_title" msgid="7313253167968363211">"已停用的服务"</string>
+    <string name="all_services_title" msgid="5578662754874906455">"所有服务"</string>
     <string name="printing_notification_title_template" msgid="295903957762447362">"正在打印“<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>”"</string>
     <string name="cancelling_notification_title_template" msgid="1821759594704703197">"正在取消打印“<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>”"</string>
     <string name="failed_notification_title_template" msgid="2256217208186530973">"打印机在打印“<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>”时出错"</string>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index a408c08..92374cb 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Wys alle ANRe"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Wys Program reageer nie-dialoog vir agtergrond programme"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Programme verplig ekstern toegelaat"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Laat enige program na ekstern geskryf word, ongeag manifeswaardes"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Maak dat enige program in eksterne berging geskryf kan word, ongeag manifeswaardes"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Verplig verstelbare groottes vir aktiwiteite"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Maak die groottes van alle aktiwiteite verstelbaar vir veelvuldige vensters, ongeag manifeswaardes."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Aktiveer vormvrye-Windows"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 7ae97e2..386d697 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"ሁሉንም ANRs አሳይ"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"ለዳራ መተግበሪያዎች ምላሽ የማይሰጥ መገናኛ ትግበራ አሳይ"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"በውጫዊ ላይ ሃይል ይፈቀዳል"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"አንጸባራቂ እሴቶች ግምት ውስጥ ሳይገቡ ማንኛውም መተግበሪያ ወደ ውጫዊ ማከማቻ ለመጻፍ ብቁ ያደርጋል።"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"የዝርዝር ሰነዶች እሴቶች ግምት ውስጥ ሳያስገባ ማንኛውም መተግበሪያ ወደ ውጫዊ ማከማቻው ለመጻፍ ብቁ ያደርጋል"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"እንቅስቃሴዎች ዳግመኛ እንዲመጣጠኑ አስገድድ"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"የዝርዝር ሰነድ እሴቶች ምንም ይሁኑ ምን ለበርካታ መስኮቶች ሁሉንም እንቅስቃሴዎች መጠናቸው የሚቀየሩ እንዲሆኑ ያደርጋቸዋል።"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"የነጻ ቅርጽ መስኮቶችን ያንቁ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index eb76e1f..2c8eda0 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"‏عرض جميع رسائل ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"عرض مربع الحوار \"التطبيق لا يستجيب\" مع تطبيقات الخلفية"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"فرض السماح للتطبيقات على الخارجي"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"تأهيل أي تطبيق بحيث تتم كتابته على سعة تخزين خارجية، بغض النظر عن قيم البيان"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"تأهيل أي تطبيق بحيث تتم كتابته على وحدة تخزين خارجية، بغض النظر عن قيم البيان"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"فرض إمكانية تغيير على الأنشطة"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"تمكين تغيير حجم جميع الأنشطة لتناسب تعدد النوافذ، بغض النظر عن قيم البيان."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"تمكين النوافذ الحرة"</string>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index 9903397..d62f472 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Bütün ANRları göstər"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Arxa tətbiqlər dialoquna cavab verməyən tətbiqi göstər"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Tətbiqlərə xaricdən məcburi icazə"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Seçilmiş hər hansı tətbiqi bəyannamə dəyərlərindən aslı olmayaraq xarici yaddaşa yazılabilən edir."</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Seçilmiş hər hansı tətbiqi bəyannamə dəyərlərindən aslı olmayaraq xarici yaddaşa yazılabilən edir."</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Ölçü dəyişdirmək üçün məcburi fəaliyyətlər"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Bəyannamə dəyərlərindən aslı olmayaraq, bütün fəaliyyətləri çoxsaylı pəncərə üçün dəyişkən ölçülü edin."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Freeform windows aktiv edin"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index f570d09..eb050de 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Prikaži dijalog Aplikacija ne reaguje za aplikacije u pozadini"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Prinudno dozvoli aplikacije u spoljnoj"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Omogućava upisivanje svih aplikacija u spoljnu memoriju, bez obzira na vrednosti manifesta"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Omogućava upisivanje svih aplikacija u spoljnu memoriju, bez obzira na vrednosti manifesta"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Prinudno omogući promenu veličine aktivnosti"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Omogući promenu veličine svih aktivnosti za režim sa više prozora, bez obzira na vrednosti manifesta."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore proizvoljnog formata"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 72652c9..7640ffd 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Всички нереагиращи прил."</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Диалог. прозорец „НП“ за приложения на заден план"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Външно хран.: Принуд. разрешаване на приложенията"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Позволява прилож. да се записват във външ. хранил. независимо от стойностите в манифеста"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Прави всички приложения да отговарят на условията да бъдат записвани във външното хранилище независимо от стойностите в манифеста"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Възможност за преоразмеряване на активностите"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Дава възможност за преоразмеряване на всички активности в режима за няколко прозореца независимо от стойностите в манифеста."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Активиране на прозорците в свободна форма"</string>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index b863773..a1063b9 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"সব ANR দেখান"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"পশ্চাদপটের অ্যাপ্লিকেশানগুলির জন্য অ্যাপ্লিকেশান কোনো প্রতিক্রিয়া দিচ্ছে না এমন কথোপকথন দেখান"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"বহিরাগততে বলপূর্বক মঞ্জুরি"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ম্যানিফেস্ট মানগুলি নির্বিশেষে যেকোনো অ্যাপ্লিকেশানকে বাহ্যিক সঞ্চয়স্থানে লেখার উপযুক্ত বানায়"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ম্যানিফেস্ট মানগুলি নির্বিশেষে যেকোনো অ্যাপ্লিকেশানকে বাহ্যিক সঞ্চয়স্থানে লেখার উপযুক্ত বানায়"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"আকার পরিবর্তনযোগ্য করার জন্য ক্রিয়াকলাপগুলিকে জোর করুন"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ম্যানিফেস্ট মানগুলির নির্বিশেষে মাল্টি-উইন্ডোর জন্য সমস্ত ক্রিয়াকলাপগুলির আকার পরিবর্তনযোগ্য করুন৷"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"ফ্রি-ফর্ম উইন্ডোগুলি সক্ষম করুন"</string>
diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml
index 542c3ce..7a87fda 100644
--- a/packages/SettingsLib/res/values-bs-rBA/strings.xml
+++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Prik. dijalog Aplikacija ne reagira za apl. u poz."</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Nametni aplikacije na vanjskoj pohrani"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Dozvoljava da bilo koja aplikacija bude upisana na vanjsku pohranu, bez obzira na vrijednosti manifesta."</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Omogućava da svaka aplikacija bude pogodna za upisivanje na vanjsku pohranu, bez obzira na prikazane vrijednosti"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Nametni aktivnostima mijenjanje veličina"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Neka sve aktivnosti budu takve da mogu mijenjati veličinu za prikaz sa više prozora, bez obzira na prikazane vrijednosti."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore nepravilnih oblika"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index e2c4495..0249282 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Tots els errors sense resposta"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Informa que una aplicació en segon pla no respon"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Força permís d\'aplicacions a l\'emmagatzem. extern"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Permet que les aplicacions es puguin escriure en un dispositiu d’emmagatzematge extern, independentment dels valors definits"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Permet que les aplicacions es puguin escriure en un dispositiu d’emmagatzematge extern, independentment dels valors definits"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Força l\'ajust de la mida de les activitats"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permet ajustar la mida de totes les activitats per al mode multifinestra, independentment dels valors definits."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Activa les finestres de format lliure"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index f713ceb..86f269d 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Zobrazit všechny ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Zobrazovat dialog „Aplikace neodpovídá“ pro aplikace na pozadí"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Vynutit povolení aplikací na externím úložišti"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Každou aplikaci bude možné zapsat do externího úložiště, bez ohledu na hodnoty manifestu"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Každou aplikaci bude možné zapsat do externího úložiště, bez ohledu na hodnoty manifestu"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Vynutit možnost změny velikosti aktivit"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Umožnit změnu velikosti všech aktivit na několik oken (bez ohledu na hodnoty manifestu)"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Aktivovat okna s volným tvarem"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index d1d7b23..720aeba 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Vis alle \"Appen svarer ikke\""</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Vis \"Appen svarer ikke\" for baggrundsapps"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Gennemtving tilladelse til eksternt lager"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Gør det muligt at overføre enhver app til et eksternt lager uafhængigt af manifestværdier"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Gør det muligt at overføre enhver app til et eksternt lager uafhængigt af manifestværdier"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Tving aktiviteter til at kunne tilpasses"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tillad, at alle aktiviteter kan tilpasses flere vinduer uafhængigt af manifestværdier."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Aktivér vinduer i frit format"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index fbd1207..ec8407b 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Alle ANRS anzeigen"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Dialogfeld \"App antwortet nicht\" für Hintergrund-Apps anzeigen"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Externe Speichernutzung von Apps erlauben"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Ermöglicht es jeder qualifizierten App, Daten auf externen Speicher zu schreiben, unabhängig von den Manifestwerten"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Ermöglicht es jeder qualifizierten App, Daten auf externen Speicher zu schreiben, unabhängig von den Manifestwerten"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Anpassen der Größe von Aktivitäten erzwingen"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Größe aller Aktivitäten an den Mehrfenstermodus anpassen, unabhängig von den Manifestwerten."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Freiform-Fenster zulassen"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index dce2cf7..7db5853 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Εμφάνιση όλων των ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Εμφ.του παραθ. \"Η εφαρμ.δεν αποκρ.\" για εφ.παρασκ."</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Να επιτρέπονται υποχρεωτικά εφαρμογές σε εξωτ.συσ."</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Κάνει κάθε εφαρμογή κατάλληλη για εγγραφή σε εξωτερικό χώρο αποθήκευσης, ανεξάρτητα από τις τιμές του μανιφέστου"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Κάνει κάθε εφαρμογή κατάλληλη για εγγραφή σε εξωτερικό αποθηκευτικό χώρο, ανεξάρτητα από τις τιμές του μανιφέστου"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Αναγκαστική δυνατότητα αλλαγής μεγέθους δραστηριοτήτων"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Να έχουν όλες οι δραστηριότητες δυνατότητα αλλαγής μεγέθους για την προβολή πολλαπλών παραθύρων, ανεξάρτητα από τις τιμές του μανιφέστου."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Ενεργοποίηση παραθύρων ελεύθερης μορφής"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 4821a71..2834031 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Show all ANRs"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Show App Not Responding dialogue for background apps"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Make all activities resizable for multi-window, regardless of manifest values."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 4821a71..2834031 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Show all ANRs"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Show App Not Responding dialogue for background apps"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Make all activities resizable for multi-window, regardless of manifest values."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 4821a71..2834031 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Show all ANRs"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Show App Not Responding dialogue for background apps"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Make all activities resizable for multi-window, regardless of manifest values."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 2d0ce02..5f7a447 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Errores sin respuesta"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Mostrar diálogo cuando las aplic. en 2do plano no responden"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permisos en almacenamiento externo"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Cualquier aplicación puede escribirse en una memoria externa, independientemente de los valores del manifiesto."</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Cualquier app puede escribirse en un almacenamiento externo, sin importar los valores del manifiesto"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar actividades para que cambien de tamaño"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permitir que todas las actividades puedan cambiar de tamaño para el modo multiventana, sin importar los valores del manifiesto."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Habilitar ventanas de forma libre"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 8dcf6ab..0314f2e 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Errores sin respuesta"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Informar de que una aplicación en segundo plano no responde"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permiso de aplicaciones de forma externa"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Hace que cualquier aplicación se pueda escribir en un dispositivo de almacenamiento externo, independientemente de los valores definidos"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Hace que cualquier aplicación se pueda escribir en un dispositivo de almacenamiento externo, independientemente de los valores definidos"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar el ajuste de tamaño de las actividades"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permite que se pueda ajustar el tamaño de todas las actividades para el modo multiventana, independientemente de los valores establecidos."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Habilitar ventanas de forma libre"</string>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index 62dd7ab..6420ccc 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Näita kõiki ANR-e"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Kuva taustarakendustele dial. Rakendus ei reageeri"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Luba rakendused välises salvestusruumis"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Lubab rakendusi kirjutada välisesse salvestusruumi olenemata manifesti väärtustest"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Lubab mis tahes rakendusi kirjutada välisesse salvestusruumi manifesti väärtustest olenemata"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Muuda tegevuste suurused muudetavaks"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Muudetakse kõigi tegevuste suurused mitme aknaga vaates muudetavaks (manifesti väärtustest olenemata)."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Luba vabas vormis aknad"</string>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index cb6f0b4..30bab3c 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Erakutsi ANR guztiak"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"\"Erantzunik ez\" mezua atz. planoko aplikazioetarako"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Behartu aplikazioak onartzea kanpoko biltegian"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Aplikazioek kanpoko memorian idatz dezakete, manifestuaren balioak kontuan izan gabe"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Aplikazioek kanpoko memorian idatz dezakete, manifestuaren balioak kontuan izan gabe"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Behartu jardueren tamaina doitu ahal izatea"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Eman aukera jarduera guztien tamaina doitzeko, hainbat leihotan erabili ahal izan daitezen, manifestuan jartzen duena jartzen duela ere."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Gaitu estilo libreko leihoak"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index e7cbd1e..f1437d7 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"‏نمایش تمام ANRها"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"نمایش گفتگوی \"برنامه پاسخ نمی‌دهد\" برای برنامه‌های پس‌زمینه"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"اجازه اجباری به برنامه‌های دستگاه ذخیره خارجی"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"بدون توجه به مقادیر مانیفست، هر برنامه‌ای را برای نوشتن در حافظه خارجی واجد شرایط می‌کند"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"بدون توجه به مقادیر مانیفست، هر برنامه‌ای را برای نوشتن در حافظه خارجی واجد شرایط می‌کند"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"اجبار فعالیت‌ها به قابل تغییر اندازه بودن"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"بدون توجه به مقادیر مانیفست، اندازه همه فعالیت‌ها برای حالت چند پنجره‌ای می‌تواند تغییر کند."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"فعال کردن پنجره‌های آزاد"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index bb3ad97..9717a78 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Näytä kaikki ANR:t"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Näytä Sovellus ei vastaa -ikkuna taustasovell."</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Salli aina ulkoinen tallennus"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Mahdollistaa sovellusten tallentamisen ulkoiseen tall.tilaan luettelosta riippumatta"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Mahdollistaa sovelluksen tietojen tallentamisen ulkoiseen tallennustilaan luetteloarvoista riippumatta."</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Pakota kaikki toiminnot hyväksymään koon muutos"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Pakota kaikki toiminnot hyväksymään koon muuttaminen usean ikkunan tilassa luettelon arvoista riippumatta."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Ota käyttöön vapaamuotoiset ikkunat"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 1f12f18..80181f0 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Afficher tous les messages «L\'application ne répond pas»"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Afficher « L\'application ne répond plus » pour applis en arrière-plan"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forcer l\'autor. d\'applis sur stockage externe"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Permet enreg. d\'applis sur espace stockage externe"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forcer les activités à être redimensionnables"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permet de redimensionner toutes les activités pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Activer les fenêtres de forme libre"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 3dc2a6a..b8ff857 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Afficher tous les messages ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Afficher \"L\'application ne répond plus\" pour applis en arrière-plan"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forcer disponibilité stockage externe pour applis"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Rend possible enregistrement de toute appli sur espace stockage externe, indépendamment valeurs fichier manifeste."</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Rend possible l\'enregistrement de toute application sur un espace de stockage externe, indépendamment des valeurs du fichier manifeste."</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forcer possibilité de redimensionner les activités"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permettre de redimensionner toutes les activités pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Activer les fenêtres de forme libre"</string>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index 3715919..2cde752 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -248,9 +248,9 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Informa que aplicación segundo plano non responde"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permiso de aplicacións de forma externa"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Fai que calquera aplicación se poida escribir nun almacenamento externo, independentemente dos valores expresados"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Permite que calquera aplicación apta se poida escribir nun almacenamento externo, independentemente dos valores expresados"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar o axuste do tamaño das actividades"</string>
-    <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permite axustar o tamaño de todas as actividades para o modo de varias ventás, independentemente dos valores definidos."</string>
+    <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permite axustar o tamaño de todas as actividades para o modo multiventá, independentemente dos valores definidos."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Activar ventás de forma libre"</string>
     <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activa a compatibilidade con ventás de forma libre experimentais."</string>
     <string name="local_backup_password_title" msgid="3860471654439418822">"Contrasinal para copias"</string>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index c77aeb6..9c25a0f 100644
--- a/packages/SettingsLib/res/values-gu-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"બધા ANR બતાવો"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"પૃષ્ઠભૂમિ એપ્લિકેશનો માટે એપ્લિકેશન પ્રતિસાદ આપતી નથી સંવાદ બતાવો"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"બાહ્ય પર એપ્લિકેશનોને મંજૂરી આપવાની ફરજ પાડો"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"મેનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, કોઈપણ એપ્લિકેશનને બાહ્ય સ્ટોરેજ પર લખાવા માટે લાયક બનાવે છે"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"મેનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, કોઈપણ ઍપ્લિકેશનને બાહ્ય સ્ટોરેજ પર લખાવા માટે લાયક બનાવે છે"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"પ્રવૃત્તિઓને ફરીથી કદ યોગ્ય થવા માટે ફરજ પાડો"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"મૅનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, તમામ પ્રવૃત્તિઓને મલ્ટી-વિંડો માટે ફરીથી કદ બદલી શકે તેવી બનાવો."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"ફ્રિફોર્મ વિંડોઝ સક્ષમ કરો"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index e8a47cb..2e1b337 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"सभी ANR दिखाएं"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"पृष्ठभूमि ऐप्स के लिए ऐप्स प्रतिसाद नहीं दे रहा डॉयलॉग दिखाएं"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"ऐप्स को बाहरी मेमोरी पर बाध्‍य करें"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"इससे कोई भी ऐप मेनिफेस्‍ट मान अनदेखा करके, बाहरी मेमोरी पर लिखने योग्‍य बन जाता है"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"इससे कोई भी ऐप्लिकेशन, मेनिफेस्ट मानों को अनदेखा करके बाहरी मेमोरी पर लिखने योग्य बन जाता है"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"आकार बदले जाने के लिए गतिविधियों को बाध्य करें"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"सभी गतिविधियों को एकाधिक विंडो के लिए आकार बदलने योग्य बनाएं, चाहे मेनिफेस्ट मान कुछ भी हों."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"फ़्रीफ़ॉर्म विंडो सक्षम करें"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 320ebc1..f9dd6b7 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Prikaz dijaloga o pozad. aplik. koja ne odgovara"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Prisilno dopusti aplikacije u vanjskoj pohrani"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Aplikacije se mogu zapisivati u vanjsku pohranu neovisno o manifestu"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Aplikacije se mogu zapisivati u vanjsku pohranu neovisno o vrijednostima manifesta"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Nametni mogućnost promjene veličine za aktivnosti"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Omogući mijenjanje veličine svih aktivnosti za više prozora, neovisno o vrijednostima manifesta."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore slobodnog oblika"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 4ea4528..94fa1bd 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Összes ANR mutatása"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Az Alkalmazás nem válaszol ablak megjelenítése"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Külső tárhely alkalmazásainak engedélyezése"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Lehetővé teszi, hogy külső tárhelyre lehessen írni"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Lehetővé teszi bármely alkalmazás külső tárhelyre való írását a jegyzékértékektől függetlenül"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Tevékenységek átméretezésének kényszerítése"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Legyen az összes tevékenység átméretezhető a többablakos megjelenítés érdekében a jegyzékértékektől függetlenül."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Szabad formájú ablakok engedélyezése"</string>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 046ea48..e9232f5 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Ցույց տալ բոլոր ANR-երը"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Ցուցադրել այն ծրագիրը, որը չի արձագանքում երկխոսությունը հետնաշերտի ծրագրերի համար"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Միշտ թույլատրել ծրագրեր արտաքին պահեստում"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Թույլ է տալիս պահել հավելվածը արտաքին սարքում՝ մանիֆեստի արժեքներից անկախ"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Թույլ է տալիս ցանկացած հավելված պահել արտաքին սարքում՝ մանիֆեստի արժեքներից անկախ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Ստիպել, որ ակտիվությունների չափերը լինեն փոփոխելի"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Բոլոր ակտիվությունների չափերը բազմապատուհան ռեժիմի համար դարձնել փոփոխելի՝ մանիֆեստի արժեքներից անկախ:"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Ակտիվացնել կամայական ձևի պատուհանները"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 02c747a..3971398 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Tampilkan semua ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Tmplkn dialog Apl Tidak Merespons utk apl ltr blkg"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Paksa izinkan aplikasi di eksternal"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksterna"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksternal, terlepas dari nilai manifes"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Paksa aktivitas agar ukurannya dapat diubah"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Buat semua aktivitas dapat diubah ukurannya untuk banyak jendela, terlepas dari nilai manifes."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Aktifkan jendela berformat bebas"</string>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index 17a2f08..7f9e768 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Öll forrit sem svara ekki"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Sýna „Forrit svarar ekki“ fyrir bakgrunnsforrit"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Þvinga fram leyfi forrita í ytri geymslu"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Gerir hvaða forriti sem er kleift að skrifa í ytri geymslu, burtséð frá gildum í upplýsingaskrá"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Gerir öll forrit skrifanleg í ytra geymslurými, óháð gildum í upplýsingaskrá"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Þvinga breytanlega stærð virkni"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gera stærð allrar virkni breytanlega svo að hún henti fyrir marga glugga, óháð gildum í upplýsingaskrá."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Virkja glugga með frjálsu sniði"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 9c75939..147ad4d 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Mostra tutti errori ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Mostra finestra ANR per applicazioni in background"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forza autorizzazione app su memoria esterna"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Rende l\'app idonea all\'installaz. su mem. esterna, senza considerare i valori manifest"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Consente l\'installazione di qualsiasi app su memoria esterna, indipendentemente dai valori manifest"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Imponi formato modificabile alle attività"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Rendi il formato di tutte le attività modificabile per la modalità multi-finestra, indipendentemente dai valori manifest."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Attiva finestre a forma libera"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 429ce61..4fce9b8 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"‏הצג את כל פריטי ה-ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"הצג תיבת דו-שיח של \'אפליקציה לא מגיבה\' עבור אפליקציות שפועלות ברקע"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"אילוץ הרשאה של אפליקציות באחסון חיצוני"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"מאפשר כתיבה של כל אפליקציה באחסון חיצוני, ללא התחשבות בערכי המניפסט"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"מאפשר כתיבה של כל אפליקציה באחסון חיצוני, ללא התחשבות בערכי המניפסט"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"אלץ יכולת קביעת גודל של הפעילויות"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"אפשר יכולת קביעת גודל של כל הפעילויות לריבוי חלונות, ללא קשר לערך המניפסט."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"הפעל את האפשרות לשנות את הגודל והמיקום של החלונות"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 6c42110..b2b3612 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"すべてのANRを表示"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"バックグラウンドアプリが応答しない場合に通知する"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"外部ストレージへのアプリの書き込みを許可"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"マニフェストの値に関係なく、すべてのアプリを外部ストレージに書き込めるようになります"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"アクティビティをサイズ変更可能にする"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"マニフェストの値に関係なく、マルチウィンドウですべてのアクティビティのサイズを変更できるようにします。"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"フリーフォーム ウィンドウの有効化"</string>
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index 6dba53b..8c34c63 100644
--- a/packages/SettingsLib/res/values-ka-rGE/strings.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"ყველა ANR-ის ჩვენება"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"შეტყობინების ჩვენება, როცა ფონური აპლიკაცია არ პასუხობს"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"აპების დაშვება გარე მეხსიერებაში"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"აპები ჩაიწერ. გარე მეხს.-ზე აღწ. ფაილის მნიშვნ. მიუხედ."</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"აპები ჩაიწერება გარე მეხსიერებაზე აღწერის ფაილების მნიშვნელობების მიუხედავად"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"ზომაცვლადი აქტივობების იძულება"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"მანიფესტის მნიშვნელობების მიუხედავად, მრავალი ფანჯრის რეჟიმისთვის ყველა აქტივობის ზომაცვლადად გადაქცევა."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"თავისუფალი ფორმის მქონე ფანჯრების ჩართვა"</string>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index 36843fd..47d3458 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Барлық ANR (қолданба жауап бермеді) хабарларын көрсетіңіз"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Фондық қолданбалардың жауап бермегенін көрсету"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Сыртқыда қолданбаларға мәжбүрлеп рұқсат ету"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест мәндеріне қарамастан кез келген қолданбаны сыртқы жадқа жазуға жарамды етеді"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Манифест мәндеріне қарамастан кез келген қолданбаны сыртқы жадқа жазуға жарамды етеді"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Әрекеттерді өлшемін өзгертуге болатын етуге мәжбүрлеу"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Манифест мәндеріне қарамастан бірнеше терезе режимінде барлық әрекеттердің өлшемін өзгертуге рұқсат беру."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Еркін пішіндегі терезелерді қосу"</string>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index 9985a1e..3f2c6c3 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"បង្ហាញ ANRs ទាំងអស់"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"បង្ហាញ​ប្រអប់​កម្មវិធី​មិន​ឆ្លើយតប​សម្រាប់​កម្មវិធី​ផ្ទៃ​ខាង​ក្រោយ"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"បង្ខំឲ្យអនុញ្ញាតកម្មវិធីលើឧបករណ៍ផ្ទុកខាងក្រៅ"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ធ្វើឲ្យកម្មវិធីទាំងឡាយមានសិទ្ធិសរសេរទៅកាន់ឧបករណ៍ផ្ទុកខាងក្រៅ ដោយមិនគិតពីតម្លៃជាក់លាក់"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"បង្ខំឲ្យសកម្មភាពអាចប្តូរទំហំបាន"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"កំណត់ឲ្យសកម្មភាពទាំងអស់អាចប្តូរទំហំបានសម្រាប់ពហុផ្ទាំងវិនដូ ដោយមិនគិតពីតម្លៃមេនីហ្វេស។"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"បើកដំណើរការផ្ទាំងវិនដូទម្រង់សេរី"</string>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index 8ca9807..009b9f7 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"ಎಲ್ಲ ANR ಗಳನ್ನು ತೋರಿಸು"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"ಹಿನ್ನೆಲೆ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್ ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತಿಲ್ಲ ಎಂಬ ಸಂಭಾಷಣೆ ತೋರಿಸು"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"ಬಾಹ್ಯವಾಗಿ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಒತ್ತಾಯವಾಗಿ ಅನುಮತಿಸಿ"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳನ್ನು ಪರಿಗಣಿಸದೇ, ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆಗೆ ಬರೆಯಲು ಅರ್ಹಗೊಳಿಸುತ್ತದೆ"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳು ಯಾವುದೇ ಆಗಿದ್ದರೂ, ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆಗೆ ಬರೆಯಲು ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಅರ್ಹಗೊಳಿಸುತ್ತದೆ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಒತ್ತಾಯ ಮಾಡಿ"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳನ್ನು ಪರಿಗಣಿಸದೇ, ಬಹು-ವಿಂಡೊಗೆ ಎಲ್ಲಾ ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಮಾಡಿ."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"ಮುಕ್ತಸ್ವರೂಪದ ವಿಂಡೊಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 31e0378..4bfdbfd 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"모든 ANR 보기"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"백그라운드 앱에 대해 앱 응답 없음 대화상자 표시"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"외부에서 앱 강제 허용"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"매니페스트 값에 관계없이 앱을 외부 저장소에 작성"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"활동의 크기가 조정 가능하도록 설정"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"모든 활동을 매니페스트 값에 관계없이 멀티 윈도우용으로 크기 조정 가능하도록 설정"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"자유 형식 창 사용"</string>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index fd2d905..d06aec5 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Бардык ANR\'лерди көрсөтүү"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Фондогу колдонмолорго Колдонмо Жооп Бербейт деп көрсөтүү"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Тышкы сактагычка сактоого уруксат берүү"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест маанилерине карабастан бардык колдонмолорду тышкы сактагычка сактоого уруксат берет"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Манифест маанилерине карабастан бардык колдонмолорду тышкы сактагычка сактоого уруксат берет"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Аракеттердин өлчөмүн өзгөртүүнү мажбурлоо"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Манифест маанилерине карабастан бардык аракеттерди мульти-терезеге өлчөмү өзгөртүлгүдөй кылуу."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Эркин формадагы терезелерди түзүүнү иштетүү"</string>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index 605f476..c5121a5 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"ສະ​ແດງ ANRs ທັງ​ຫມົດ"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"ສະແດງໜ້າຈໍແອັບຯທີ່ບໍ່ຕອບສະໜອງສຳລັບແອັບຯພື້ນຫຼັງ"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"ບັງຄັບອະນຸຍາດແອັບ​ຢູ່​ພາຍນອກ"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ເຮັດ​ໃຫ້ທຸກແອັບ​ມີ​ສິດ​ໄດ້ຮັບການຂຽນ​ໃສ່​ບ່ອນ​ຈັດ​ເກັບ​ພາຍນອກ, ໂດຍ​ບໍ່​ຄຳ​ນຶງ​ເຖິງ​ຄ່າ​ທີ່​ຈະ​ແຈ້ງ"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"ບັງ​ຄັງ​ໃຫ້​ກິດ​ຈະ​ກຳ​ປ່ຽນ​ຂະ​ໜາດ​ໄດ້"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ເຮັດໃຫ້ທຸກກິດຈະກຳສາມາດປັບຂະໜາດໄດ້ສຳລັບຫຼາຍໜ້າຈໍ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າ manifest."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"ເປີດໃຊ້ໜ້າຕ່າງຮູບແບບອິດສະຫຼະ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 253eeb3..dd1ccc8 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Rodyti visus ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Fon. programose rodyti dialogo langą „Neatsako“"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Priverstinai leisti programas išorinėje atmintin."</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Vis. pr. gal. įr. į vid. saug. nepais. apr. vert."</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Nustatoma, kad visas programas būtų galima įrašyti į išorinę saugyklą, nepaisant aprašo verčių"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Priv. nust., kad veiksm. b. g. atl. kelių d. lang."</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Nustatyti, kad visus veiksmus būtų galima atlikti kelių dydžių languose, nepaisant aprašo verčių."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Įgalinti laisvos formos langus"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 3323cd9..009ccf6 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Rādīt visus ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Rādīt fona lietotņu dialoglodz. Lietotne nereaģē"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Lietotņu piespiedu atļaušana ārējā krātuvē"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Ļauj jebkuru lietotni ierakstīt ārējā krātuvē neatkarīgi no manifesta vērtības."</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Ļauj jebkuru lietotni ierakstīt ārējā krātuvē neatkarīgi no manifesta vērtības."</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Pielāgot darbības"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Pielāgot visas darbības vairāku logu režīmam neatkarīgi no vērtībām manifestā."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Iespējot brīvās formas logus"</string>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index 41c8600..0c2ddf4 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Прикажи ги сите ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Прикажи „Апл. не реагира“ за. апл. во заднина"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Принуд. дозволете апликации на надворешна меморија"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Запишува апл. во надв.меморија, незав. од манифест"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"Принуди ги активностите да ја менуваат големината"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Направете сите активности да бидат со променлива големина за повеќе прозорци, без разлика на вредностите на манифестот."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Овозможи прозорци со слободна форма"</string>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index 80cf43e..3b4acd2 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"എല്ലാ ANR-കളും ദൃശ്യമാക്കുക"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"പ‌ശ്ചാത്തല അപ്ലിക്കേഷനുകൾക്ക് അപ്ലിക്കേഷൻ പ്രതികരിക്കുന്നില്ല എന്ന ഡയലോഗ് കാണിക്കുക"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"ബാഹ്യമായതിൽ നിർബന്ധിച്ച് അനുവദിക്കുക"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, ബാഹ്യ സ്റ്റോറേജിലേക്ക് എഴുതപ്പെടുന്നതിന് ഏതൊരു ആപ്പിനെയും യോഗ്യമാക്കുന്നു"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"വലിപ്പം മാറ്റാൻ പ്രവർത്തനങ്ങളെ നിർബന്ധിക്കുക"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, എല്ലാ ആക്ടിവിറ്റികളെയും മൾട്ടി-വിൻഡോയ്ക്കായി വലിപ്പം മാറ്റുക."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"ഫ്രീഫോം വിൻഡോകൾ പ്രവർത്തനക്ഷമമാക്കുക"</string>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index 5e7ea15..4473f7f 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Бүх ANRs харуулах"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Далд апп-уудад Апп Хариу Өгөхгүй байна гэснийг харуулах"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Апп-ыг гадаад санах ойд хадгалахыг зөвшөөрөх"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест утгыг нь үл хамааран дурын апп-ыг гадаад санах ойд бичих боломжтой болгодог"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"Үйл ажиллагааны хэмжээг өөрчилж болохуйц болгох"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Тодорхойлогч файлын утгыг үл хамааран, бүх үйл ажиллагааны хэмжээг олон цонхонд өөрчилж болохуйц болгоно уу."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Чөлөөт хэлбэрийн цонхыг идэвхжүүлэх"</string>
diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml
index 7a3d76d..d8075aa 100644
--- a/packages/SettingsLib/res/values-mr-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"सर्व ANR दर्शवा"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"पार्श्वभूमी अॅप्ससाठी अॅप प्रतिसाद देत नाही संवाद दर्शवा"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"बाह्यवर अॅप्सना अनुमती देण्याची सक्ती करा"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"मॅनिफेस्ट मूल्यांकडे दुर्लक्ष करून, कोणत्याही अॅपला बाह्य संचयनावर लेखन केले जाण्‍यासाठी पात्र बनविते"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"मॅनिफेस्ट मूल्यांकडे दुर्लक्ष करून, कोणत्याही अॅपला बाह्य संचयनावर लेखन केले जाण्यासाठी पात्र बनविते"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"क्र‍ियाकलापाचा आकार बदलण्यायोग्य होण्याची सक्ती करा"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"मॅनिफेस्ट मूल्यांकडे दुर्लक्ष करून, एकाधिक-विंडोसाठी सर्व क्रियाकलापांचा आकार बदलण्यायोग्य करा."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"freeform विंडो सक्षम करा"</string>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index 3f29687..44ed1f6 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Tunjukkan semua ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Tunjukkan dialog Aplikasi Tidak Memberi Maklum Balas untuk aplikasi latar belakang"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Benarkan apl secara paksa pada storan luaran"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Menjadikan sebarang apl layak ditulis ke storan luaran, walau apa juga nilai manifesnya"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"Paksa aktiviti supaya boleh diubah saiz"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Bolehkan semua saiz aktiviti diubah untuk berbilang tetingkap, tanpa mengambil kira nilai manifes."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Dayakan tetingkap bentuk bebas"</string>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index 71862a3..bf2ea80 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"ANRsအားလုံးအား ပြသရန်"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"နောက်ခံအပ်ပလီကေးရှင်းအတွက်တုံ့ပြန်မှုမရှိပြရန်"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"အပြင်မှာ အတင်း ခွင့်ပြုရန်"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ပြနေတဲ့ တန်ဖိုး ဘယ်လိုပဲရှိနေနေ၊ ဘယ် appကို မဆို အပြင် သိုလှောင်ခန်းသို့ ရေးသားခွင့် ပေးတယ်"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"တိကျစွာ သတ်မှတ်ထားသည့်တန်ဖိုးများရှိသော်လည်း၊ ပြင်ပသိုလှောင်ခန်းများသို့ မည်သည့်အက်ပ်ကိုမဆို သိမ်းဆည်းခွင့်ပြုပါ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"လုပ်ဆောင်ချက်များ ဆိုက်ညှိရနိုင်ရန် လုပ်ခိုင်းပါ"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"မန်နီးဖက်စ်တန်ဖိုးများ မည်မျှပင်ရှိစေကာမူ၊ ဝင်းဒိုးများအတွက် လှုပ်ရှားမှုများအားလုံးကို အရွယ်အစားချိန်ခြင်း ပြုလုပ်ပါ။"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"အခမဲ့ပုံစံ ဝင်းဒိုးကို ဖွင့်ပါ"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 2ad14dc..94993d4 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Vis alle ANR-er"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Vis Appen svarer ikke-dialog for bakgrunnsapper"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Tving frem tillatelse for ekstern lagring av apper"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Gjør at apper kan skrives til ekstern lagring, uavhengig av manifestverdier"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Dette gjør at alle apper kan lagres på ekstern lagring – uavhengig av manifestverdier"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Tving aktiviteter til å kunne endre størrelse"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gjør at alle aktivitetene kan endre størrelse for flervindusmodus, uavhengig av manifestverdier."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Slå på vinduer i fritt format"</string>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index 6c8dc59..8d25315 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"सबै ANRs देखाउनुहोस्"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"पृष्ठभूमि अनुप्रयोगका लागि जवाफ नदिइरहेका अनुप्रयोगहरू देखाउनुहोस्"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"बाह्यमा बल प्रयोगको अनुमति प्राप्त अनुप्रयोगहरू"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"म्यानिफेेस्टको उपेक्षा गरी, कुनै पनि अनुप्रयोगलाई बाह्य भण्डारणमा लेख्न योग्य बनाउँछ"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"म्यानिफेेस्टका मानहरूको ख्याल नगरी कुनै पनि अनुप्रयोगलाई बाह्य भण्डारणमा लेख्न सकिने खाले बनाउँछ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"गतिविधिहरू रिसाइज गर्नको लागि बाध्य गर्नुहोस्"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"म्यानिफेेस्ट मानहरूको ख्याल नगरी, बहु-विन्डोको लागि सबै रिसाइज गर्न सकिने गतिविधिहरू बनाउनुहोस्।"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"फ्रिफर्म विन्डोहरू सक्रिय गर्नुहोस्"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 7f9df25..c60e9df 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Alle ANR\'s weergeven"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"\'App reageert niet\' weerg. voor apps op achtergr."</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Toestaan van apps op externe opslag afdwingen"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Hierdoor komt een app in aanmerking om te worden geschreven naar externe opslag, ongeacht de manifestwaarden"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Hiermee komt elke app in aanmerking voor schrijven naar externe opslag, ongeacht de manifestwaarden"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Formaat activiteiten geforceerd aanpasbaar maken"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Het formaat van alle activiteiten aanpasbaar maken, ongeacht de manifestwaarden."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Vensters met vrije vorm inschakelen"</string>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index 10d57f4..3771536 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"ਸਾਰੇ ANR ਦਿਖਾਓ"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"ਪਿਛੋਕੜ ਐਪਸ ਲਈ ਐਪਸ ਜਵਾਬ ਨਹੀਂ ਦੇ ਰਹੇ ਡਾਇਲੌਗ ਦਿਖਾਓ"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"ਐਪਸ ਨੂੰ ਬਾਹਰਲੇ ਤੇ ਜ਼ਬਰਦਸਤੀ ਆਗਿਆ ਦਿਓ"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ਇੱਕ ਐਪ ਨੂੰ ਬਾਹਰਲੀ ਸਟੋਰੇਜ ਤੇ ਲਿਖਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ, ਮੈਨੀਫੈਸਟ ਵੈਲਯੂਜ ਤੇ ਵਿਚਾਰ ਕੀਤੇ ਬਿਨਾਂ"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ਮੈਨੀਫੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਕਿਸੇ ਵੀ ਐਪ ਨੂੰ ਬਾਹਰੀ ਸਟੋਰੇਜ \'ਤੇ ਲਿਖਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦੀ ਹੈ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"ਮੁੜ-ਆਕਾਰ ਬਦਲਣ ਲਈ ਸਰਗਰਮੀਆਂ \'ਤੇ ਜ਼ੋਰ ਦਿਓ"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ਮੈਨੀਫੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਮਲਟੀ-ਵਿੰਡੋ ਲਈ ਸਾਰੀਆਂ ਸਰਗਰਮੀਆਂ ਨੂੰ ਆਕਾਰ ਬਦਲਣਯੋਗ ਬਣਾਓ।"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"freeform windows ਨੂੰ ਯੋਗ ਬਣਾਓ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 3e89094..cd4cc83 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Pokaż wszystkie ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Pokaż okno Aplikacja Nie Reaguje dla aplikacji w tle"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Wymuś zezwalanie na aplikacje w pamięci zewn."</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Pozwala na zapis aplikacji w pamięci zewn. niezależnie od wartości w pliku manifestu"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Pozwala na zapis aplikacji w pamięci zewnętrznej niezależnie od wartości w pliku manifestu"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Wymuś zmianę rozmiaru okien aktywności"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Zezwól na zmianę rozmiaru wszystkich okien aktywności w trybie wielu okien niezależnie od ustawień w pliku manifestu."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Włącz dowolny rozmiar okien"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index c772ded..64a97b9 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANRS"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Exibir \"App não responde\" para app em 2º plano"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps em armazenamento externo"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Qualifica apps p/ gravação em armazenamento externo, independentemente de valores de manifestos"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Qualifica apps para gravação em armazenamento externo, independentemente de valores de manifestos"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 2b3dcc7..b648589 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Mostrar erro \"Aplic. não Resp.\" p/ aplic. 2º plano"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar perm. de aplicações no armazenamento ext."</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Qualquer aplic. pode ser gravada no arm. ext., independ. dos valores do manif."</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Torna qualquer aplicação elegível para ser gravada no armazenamento externo, independentemente dos valores do manifesto"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar as atividades a serem redimensionáveis"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index c772ded..64a97b9 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANRS"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Exibir \"App não responde\" para app em 2º plano"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps em armazenamento externo"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Qualifica apps p/ gravação em armazenamento externo, independentemente de valores de manifestos"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Qualifica apps para gravação em armazenamento externo, independentemente de valores de manifestos"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 0322f55..b0c5064 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Afișați toate elem. ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Aplicații din fundal: afișați Aplicația nu răspunde"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forțați accesul aplicațiilor la stocarea externă"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Face orice aplicație eligibilă să fie scrisă în stocarea externă, indiferent de valorile manifestului"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Face orice aplicație eligibilă să fie scrisă în stocarea externă, indiferent de valorile manifestului"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forțați redimensionarea activităților"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permiteți redimensionarea tuturor activităților pentru modul cu ferestre multiple, indiferent de valorile manifestului."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Activați ferestrele cu formă liberă"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 7548ace..4aa4c10 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Все ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Уведомлять о том, что приложение не отвечает"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Разрешить сохранение на внешние накопители"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Разрешает сохранение приложений на внешние накопители независимо от значения манифеста"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Разрешает сохранение приложений на внешних накопителях независимо от значений манифеста"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Изменение размера в многооконном режиме"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Разрешить изменение размера в многооконном режиме (независимо от значений манифеста)"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Разрешить создание окон произвольной формы"</string>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index f3d6dc3..b5053dd 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"සියලුම ANR පෙන්වන්න"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"පසුබිම් යෙදුම් වලට යෙදුම ප්‍රතිචාර නොදක්වයි කවුළුව පෙන්වන්න"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"බාහිර මත යෙදුම් ඉඩ දීම බල කරන්න"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"මැනිෆෙස්ට් අගයන් නොසලකා, ඕනෑම යෙදුමක් අභ්‍යන්තර ගබඩාවට ලිවීමට සුදුසුකම් ලබා දෙයි"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"ක්‍රියාකාරකම් ප්‍රතිප්‍රමාණ කළ හැකි බවට බල කරන්න"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"මැනිෆෙස්ට් අගයන් නොසලකා, සියලු ක්‍රියාකාරකම් බහු-කවුළුව සඳහා ප්‍රතිප්‍රමාණ කළ හැකි බවට පත් කරන්න."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"අනියම් හැඩැති කවුළු සබල කරන්න"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 712c348..852bd9e 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Zobrazovať všetky ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Zobrazovať dialóg „Aplikácia neodpovedá“ aj pre aplikácie na pozadí"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Vynútiť povolenie aplikácií na externom úložisku"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Umožňuje zapísať akúkoľvek aplikáciu do externého úložiska bez ohľadu na hodnoty v manifeste"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Umožňuje zapísať akúkoľvek aplikáciu do externého úložiska bez ohľadu na hodnoty v manifeste"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Vynútiť možnosť zmeny veľkosti aktivít"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Veľkosti všetkých aktivít bude možné zmeniť na niekoľko okien (bez ohľadu na hodnoty manifestu)."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Povoliť okná s voľným tvarom"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 2f23144..830399f 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Pokaži okna neodzivanj"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Prikaz pogovornega okna za neodzivanje aplikacije v ozadju"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Vsili omogočanje aplikacij v zunanji shrambi"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsako aplikacijo zapisati v zunanjo shrambo"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsako aplikacijo zapisati v zunanjo shrambo"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Vsili povečanje velikosti za aktivnosti"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsem aktivnostim povečati velikost za način z več okni."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Omogočanje oken svobodne oblike"</string>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index 853dd2f..10b9134 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Shfaq raportet ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Shfaq raportet ANR (Aplikacioni nuk përgjigjet) për aplikacionet në sfond"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Detyro lejimin në hapësirën e jashtme"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Bën që çdo aplikacion të jetë i përshtatshëm për t\'u shkruar në hapësirën ruajtëse të jashtme, pavarësisht nga vlerat e manifestit"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Bën që çdo aplikacion të jetë i përshtatshëm për t\'u shkruar në hapësirën ruajtëse të jashtme, pavarësisht nga vlerat e manifestit"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Detyro madhësinë e ndryshueshme për aktivitetet"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Bëj që të gjitha aktivitetet të kenë madhësi të ndryshueshme për përdorimin me shumë dritare, pavarësisht vlerave të manifestit."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Aktivizo dritaret me formë të lirë"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 094a405..51b2b10 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Прикажи све ANR-ове"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Прикажи дијалог Апликација не реагује за апликације у позадини"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Принудно дозволи апликације у спољној"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Омогућава уписивање свих апликација у спољну меморију, без обзира на вредности манифеста"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Омогућава уписивање свих апликација у спољну меморију, без обзира на вредности манифеста"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Принудно омогући промену величине активности"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Омогући промену величине свих активности за режим са више прозора, без обзира на вредности манифеста."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Омогући прозоре произвољног формата"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index e12d394..c19f7f4 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Visa alla som inte svarar"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Visa dialogrutan om att appen inte svarar för bakgrundsappar"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Tillåt appar i externt lagringsutrymme"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Appen kan skrivas till extern lagring, oavsett manifestvärden"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Allar appar kan skrivas till extern lagring, oavsett manifestvärden"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Framtvinga storleksanpassning för aktiviteter"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gör det möjligt att ändra storleken på alla aktiviteter i flerfönsterläge, oavsett manifestvärden."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Aktivera frihandsfönster"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index d5a9d1b..091a447 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Onyesha ANR zote"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Onyesha kisanduku kidadisi cha Programu Haiitikii kwa programu za usuli"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Lazima uruhusu programu kwenye hifadhi ya nje"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Huweka programu kwenye hifadhi ya nje, bila kujali maelezo"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Huruhusu programu yoyote iwekwe kwenye hifadhi ya nje, bila kujali thamani za faili ya maelezo"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Lazimisha shughuli ziweze kubadilishwa ukubwa"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Fanya shughuli zote ziweze kubadilishwa ukubwa kwenye madirisha mengi, bila kuzingatia thamani za faili ya maelezo."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Washa madirisha yenye muundo huru"</string>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index 5c7732f..105b980 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"எல்லா ANRகளையும் காட்டு"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"பின்புலப் பயன்பாடுகளுக்குப் பயன்பாடு பதிலளிக்கவில்லை என்ற உரையாடலைக் காட்டு"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"பயன்பாடுகளை வெளிப்புறச் சேமிப்பிடத்தில் அனுமதி"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"மேனிஃபெஸ்ட் மதிப்புகளை பொருட்படுத்தாமல், எந்தப் பயன்பாட்டையும் வெளிப்புற சேமிப்பிடத்தில் எழுத அனுமதிக்கும்"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"செயல்பாடுகளை அளவுமாறக்கூடியதாக அமை"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், பல சாளரத்திற்கு எல்லா செயல்பாடுகளையும் அளவுமாறக்கூடியதாக அமை."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"குறிப்பிட்ட வடிவமில்லாத சாளரங்களை இயக்கு"</string>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index a74fc82..91ee5fa 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"అన్ని ANRలను చూపు"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"నేపథ్య అనువర్తనాల కోసం అనువర్తనం ప్రతిస్పందించడం లేదు డైలాగ్‌ను చూపు"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"అనువర్తనాలను బాహ్య నిల్వలో నిర్బంధంగా అనుమతించు"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ఏ అనువర్తనాన్ని అయినా మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా బాహ్య నిల్వలో వ్రాయగలిగేలా అనుమతిస్తుంది"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ఏ అనువర్తనాన్ని అయినా మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా బాహ్య నిల్వలో వ్రాయడానికి అనుమతిస్తుంది"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"కార్యాచరణలను పరిమాణం మార్చగలిగేలా నిర్బంధించు"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా అన్ని కార్యాచరణలను పలు రకాల విండోల్లో సరిపోయేట్లు పరిమాణం మార్చగలిగేలా చేస్తుంది."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"స్వతంత్ర రూప విండోలను ప్రారంభించండి"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 53caea5..b5ec3d9 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"แสดง ANR ทั้งหมด"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"แสดงหน้าต่างแอปไม่ตอบสนอง สำหรับแอปพื้นหลัง"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"บังคับให้แอปสามารถใช้ที่เก็บภายนอก"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ให้สามารถเขียนแอปต่างๆ ไปยังที่เก็บภายนอกได้ โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"บังคับให้กิจกรรมปรับขนาดได้"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ทำให้กิจกรรมทั้งหมดปรับขนาดได้สำหรับหน้าต่างหลายบาน โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"เปิดใช้หน้าต่างรูปแบบอิสระ"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 0c1f167..d3bcc5f 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Ipakita ang lahat ng ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"App Not Responding dialog para sa background apps"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Pwersahang payagan ang mga app sa external"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Mara-write na sa external storage ang anumang app, anuman ang manifest value"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"Sapilitang gawing resizable ang mga aktibidad"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gawing nare-resize ang lahat ng aktibidad para sa multi-window, anuman ang mga value ng manifest."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"I-enable ang mga freeform window"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 230da22..a8f2620 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Tüm ANR\'leri göster"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Arka plan uygulamalar için Uygulama Yanıt Vermiyor mesajını göster"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Harici birimdeki uygulamalara izin vermeye zorla"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Bildirilen değerlerden bağımsız olarak uygulamaları harici depolamaya yazmak için uygun hale getirir"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"Etkinlikleri yeniden boyutlandırılabilmeye zorla"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Manifest değerlerinden bağımsız olarak, tüm etkinlikleri birden fazla pencerede yeniden boyutlandırılabilir yap."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Serbest biçimli pencereleri etkinleştir"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 01cedc6..d094ef7 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Показувати всі ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Сповіщати, коли додаток не відповідає"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Примусово записувати додатки в зовнішню пам’ять"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Додатки можна записувати на зовнішню пам’ять незалежно від значень маніфесту"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Можна записувати додатки в зовнішню пам’ять, незалежно від значень у маніфесті"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Примусово масштабувати активність"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Масштабувати активність на кілька вікон, незалежно від значень у файлі маніфесту."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Увімкнути вікна довільного формату"</string>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index 878ff0c..27046dc 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"‏سبھی ANRs کو دکھائیں"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"پس منظر کی ایپس کیلئے ایپ جواب نہیں دے رہی ہے ڈائلاگ دکھائیں"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"بیرونی پر ایپس کو زبردستی اجازت دیں"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"‏manifest اقدار سے قطع نظر، کسی بھی ایپ کو بیرونی اسٹوریج پر لکھے جانے کا اہل بناتا ہے"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"‏manifest اقدار سے قطع نظر، کسی بھی ایپ کو بیرونی اسٹوریج پر لکھے جانے کا اہل بناتا ہے"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"سرگرمیوں کو ری سائز ایبل بنائیں"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"‏manifest اقدار سے قطع نظر، ملٹی ونڈو کیلئے تمام سرگرمیوں کو ری سائز ایبل بنائیں۔"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"‏freeform ونڈوز فعال کریں"</string>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index d81a041..031f8f7 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Hamma ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Ilova javob bermayotgani haqida xabar qilish"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Tashqi xotira qurilmasidagi ilova dasturlariga majburiy ruxsat berish"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Manifest qiymatidan qat’i nazar istalgan ilovani tashqi xotiraga saqlash imkonini beradi"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Manifest qiymatidan qat’i nazar istalgan ilovani tashqi xotiraga saqlash imkonini beradi"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Harakatlarni moslashuvchan o‘lchamga keltirish"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Manifest qiymatidan qat’i nazar barcha harakatlarni ko‘p oynali rejimga moslashtirish."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Erkin shakldagi oynalarni yoqish"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 2b4bddd..f3fb96a 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Hiển thị tất cả ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Hiện hộp thoại Ứng dụng ko đáp ứng cho ứng dụng nền"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Buộc cho phép các ứng dụng trên bộ nhớ ngoài"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Giúp ứng dụng bất kỳ đủ điều kiện được ghi vào bộ nhớ ngoài bất kể giá trị tệp kê khai là gì"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"Buộc các hoạt động có thể thay đổi kích thước"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Giúp tất cả hoạt động có thể thay đổi kích thước cho nhiều cửa sổ bất kể giá trị tệp kê khai là gì."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Bật cửa sổ dạng tự do"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 48f03b7..348a319 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"显示所有“应用无响应”(ANR)"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"为后台应用显示“应用无响应”对话框"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"强制允许将应用写入外部存储设备"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"允许将任何应用写入外部存储设备(无论清单值是什么)"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"强制将活动设为可调整大小"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"将所有 Activity 设为可配合多窗口环境调整大小(忽略清单值)。"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"启用可自由调整的窗口"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 38656e5..6adabc9 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"顯示所有 ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"顯示背景應用程式的「應用程式無回應」對話框"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"強制允許應用程式寫入到外部儲存空間"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"允許將所有應用程式寫入到外部儲存完間 (所有資訊清單值)"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"強制可變更活動尺寸"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"在任何資訊清單值下,允許系統配合多重視窗環境調整所有活動的尺寸。"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"啟用自由形態視窗"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index af83365..f4aade0 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -248,7 +248,8 @@
     <string name="show_all_anrs" msgid="28462979638729082">"顯示所有無回應程式"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"為背景應用程式顯示「應用程式無回應」對話方塊"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"強制允許將應用程式寫入外部儲存空間"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"允許將任何應用程式寫入外部儲存空間 (無論資訊清單值為何)"</string>
+    <!-- no translation found for force_allow_on_external_summary (3640752408258034689) -->
+    <skip />
     <string name="force_resizable_activities" msgid="8615764378147824985">"將活動強制設為可調整大小"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"將所有活動設為可配合多重視窗環境調整大小 (無論資訊清單值為何)。"</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"啟用自由形式視窗"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 16841d3..268cdb2 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -248,7 +248,7 @@
     <string name="show_all_anrs" msgid="28462979638729082">"Bonisa wonke ama-ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Boniso idayalogi Yohlelo Lokusebenza Olungasabeli kwizinhlelo zokusebenza zasemuva"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Phoqelela ukuvumela izinhlelo zokusebenza ngaphandle"</string>
-    <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Yenza noma uluphi uhlelo lokusebenza lifaneleke ukuthi libhalwe kusitoreji sangaphandle, ngaphandle kwamavelu we-manifest"</string>
+    <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Yenza noma uluphi uhlelo lokusebenza lifaneleke ukuthi libhalwe kusitoreji sangaphandle, ngaphandle kwamavelu we-manifest"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Imisebenzi yamandla izonikezwa usayizi omusha"</string>
     <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Yenza yonke imisebenzi ibe nosayizi abasha kumawindi amaningi, ngokunganaki amavelu e-manifest."</string>
     <string name="enable_freeform_support" msgid="1461893351278940416">"Nika amandla amawindi e-freeform"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index ef397f6..1aee490 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -625,7 +625,7 @@
     <!-- UI debug setting: force allow apps on external storage [CHAR LIMIT=50] -->
     <string name="force_allow_on_external">Force allow apps on external</string>
     <!-- UI debug setting: force allow on external summary [CHAR LIMIT=150] -->
-    <string name="force_allow_on_external_summary">Makes any app elligible to be written to external storage, regardless of manifest values</string>
+    <string name="force_allow_on_external_summary">Makes any app eligible to be written to external storage, regardless of manifest values</string>
 
     <!-- UI debug setting: force all activites to be resizable for multiwindow [CHAR LIMIT=50] -->
     <string name="force_resizable_activities">Force activities to be resizable</string>
@@ -687,7 +687,7 @@
     <!-- Developer settings: select WebView provider dialog title [CHAR LIMIT=30] -->
     <string name="select_webview_provider_dialog_title">Set WebView implementation</string>
     <!-- Developer settings: text for the WebView provider selection toast shown if an invalid provider was chosen (i.e. the setting list was stale). [CHAR LIMIT=NONE] -->
-    <string name="select_webview_provider_toast_text">The chosen WebView implementation is invalid because the list of implementation choices grew stale. The list should now be updated.</string>
+    <string name="select_webview_provider_toast_text">This choice is no longer valid. Try again.</string>
 
     <!-- Developer settings screen, convert userdata to file encryption option name -->
     <string name="convert_to_file_encryption">Convert to file encryption</string>
@@ -775,7 +775,7 @@
 
     <!-- Summary for switch preference to denote it is switched on [CHAR LIMIT=50] -->
     <string name="enabled_by_admin">Enabled by administrator</string>
-    <!-- Summary for switch preference to denote it is switched on [CHAR LIMIT=50] -->
+    <!-- Summary for switch preference to denote it is switched off [CHAR LIMIT=50] -->
     <string name="disabled_by_admin">Disabled by administrator</string>
 
     <!-- Option in navigation drawer that leads to Settings main screen [CHAR LIMIT=30] -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index d0c249f..1f1a9b8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -651,8 +651,11 @@
             final int disabledColor = context.getColor(R.color.disabled_text_color);
             sb.setSpan(new ForegroundColorSpan(disabledColor), 0, sb.length(),
                     Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
-            final ImageSpan image = new RestrictedLockImageSpan(context);
-            sb.append(" ", image, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            textView.setCompoundDrawables(null, null, getRestrictedPadlock(context), null);
+            textView.setCompoundDrawablePadding(context.getResources().getDimensionPixelSize(
+                    R.dimen.restricted_icon_padding));
+        } else {
+            textView.setCompoundDrawables(null, null, null, null);
         }
         textView.setText(sb);
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
index 62c213a..d0aba22 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -145,13 +145,14 @@
      */
     public boolean setDisabledByAdmin(EnforcedAdmin admin) {
         final boolean disabled = (admin != null ? true : false);
-        mEnforcedAdmin = (disabled ? admin : null);
-        mPreference.setEnabled(!disabled);
+        mEnforcedAdmin = admin;
+        boolean changed = false;
         if (mDisabledByAdmin != disabled) {
             mDisabledByAdmin = disabled;
-            return true;
+            changed = true;
         }
-        return false;
+        mPreference.setEnabled(!disabled);
+        return changed;
     }
 
     public boolean isDisabledByAdmin() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index fa2226d..74c1ebd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -151,10 +151,17 @@
         if (sSystemSignature == null) {
             sSystemSignature = new Signature[]{ getSystemSignature(pm) };
         }
-        return sSystemSignature[0] != null && sSystemSignature[0].equals(getFirstSignature(pkg));
+        if (sPermissionControllerPackageName == null) {
+            sPermissionControllerPackageName = pm.getPermissionControllerPackageName();
+        }
+        return (sSystemSignature[0] != null
+                        && sSystemSignature[0].equals(getFirstSignature(pkg)))
+                || (sPermissionControllerPackageName != null
+                        && sPermissionControllerPackageName.equals(pkg.packageName));
     }
 
     private static Signature[] sSystemSignature;
+    private static String sPermissionControllerPackageName;
 
     private static Signature getFirstSignature(PackageInfo pkg) {
         if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
index 9268994..fcff305 100644
--- a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
@@ -145,11 +145,6 @@
         Settings.Secure.putStringForUser(context.getContentResolver(),
                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
                 enabledServicesBuilder.toString(), userId);
-
-        // Update accessibility enabled.
-        Settings.Secure.putIntForUser(context.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_ENABLED, accessibilityEnabled ? 1 : 0,
-                userId);
     }
 
     private static Set<ComponentName> getInstalledServices(Context context) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 7a1c741..ce69c5a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -103,16 +103,6 @@
     }
 
     @Override
-    public void onBackPressed() {
-        if (mShowingMenu) {
-            // If we are showing the menu, then we are a top level activity and the back should
-            // kick back to settings home.
-            openTile(null);
-        }
-        super.onBackPressed();
-    }
-
-    @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         if (mShowingMenu && mDrawerLayout != null && item.getItemId() == android.R.id.home
                 && mDrawerAdapter.getCount() != 0) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 987b5ea..743912a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -207,6 +207,10 @@
 
     @Override
     public Bundle call(String method, String name, Bundle args) {
+        // If the remote side sent us bad parcelables, they won't get the
+        // results they want, which is their loss.
+        if (args != null) args.setDefusable(true);
+
         final int requestingUserId = getRequestingUserId(args);
         switch (method) {
             case Settings.CALL_METHOD_GET_GLOBAL: {
diff --git a/packages/Shell/res/layout/dialog_bugreport_info.xml b/packages/Shell/res/layout/dialog_bugreport_info.xml
index b6b8d6b..bb3084f 100644
--- a/packages/Shell/res/layout/dialog_bugreport_info.xml
+++ b/packages/Shell/res/layout/dialog_bugreport_info.xml
@@ -19,6 +19,7 @@
     android:paddingTop="15dp"
     android:paddingStart="24dp"
     android:paddingEnd="24dp"
+    android:focusableInTouchMode="true"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">
     <TextView
@@ -30,7 +31,6 @@
         android:id="@+id/name"
         android:maxLength="30"
         android:singleLine="true"
-        android:selectAllOnFocus="true"
         android:inputType="textNoSuggestions"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"/>
diff --git a/packages/Shell/res/values-af/strings.xml b/packages/Shell/res/values-af/strings.xml
index f86b551..8dbe3cd 100644
--- a/packages/Shell/res/values-af/strings.xml
+++ b/packages/Shell/res/values-af/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Tuisskerm"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Foutverslag <xliff:g id="ID">#%d</xliff:g> word tans geskep"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Foutverslag <xliff:g id="ID">#%d</xliff:g> is vasgevang"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Foutverslag <xliff:g id="ID">#%d</xliff:g> vasgevang, maar skermkiekie hangende"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Voeg tans besonderhede by die foutverslag"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Wag asseblief …"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swiep na links om jou foutverslag te deel"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tik om jou foutverslag te deel"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tik om jou foutverslag sonder \'n skermkiekie te deel, of wag totdat die skermkiekie gereed is"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tik om jou foutverslag sonder \'n skermkiekie te deel, of wag totdat die skermkiekie gereed is"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Foutverslae bevat data van die stelsel se verskillende loglêers af, insluitend persoonlike en private inligting. Deel foutverslae net met programme en mense wat jy vertrou."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Wys hierdie boodskap volgende keer"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Foutverslae"</string>
diff --git a/packages/Shell/res/values-am/strings.xml b/packages/Shell/res/values-am/strings.xml
index 55c5390..b0d3de0 100644
--- a/packages/Shell/res/values-am/strings.xml
+++ b/packages/Shell/res/values-am/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"ቀፎ"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"የሳንካ ሪፖርት <xliff:g id="ID">#%d</xliff:g> እየተመነጨ ነው"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"የሳንካ ሪፖርት <xliff:g id="ID">#%d</xliff:g> ተወስዷል"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"የሳንካ ሪፖርት <xliff:g id="ID">#%d</xliff:g> ፎቶ ተነስቷል፣ ነገር ግን ቅጽበታዊ ገጽ ማያ በመጠባበቅ ላይ ነው"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ዝርዝሮችን ወደ የሳንካ ሪፖርቱ በማከል ላይ"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"እባክዎ ይጠብቁ…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"የሳንካ ሪፖርትዎን ለማጋራት ወደ ግራ ያንሸራትቱ"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"የሳንካ ሪፖርትዎን ለማጋራት መታ ያድርጉ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"የእርስዎን የሳንካ ሪፖርት ያለ ቅጽበታዊ ማያ ገጽ ለማጋራት መታ ያድርጉ ወይም ቅጽበታዊ ማያ ገጹ እስኪጨርስ ይጠብቁ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"የእርስዎን የሳንካ ሪፖርት ያለ ቅጽበታዊ ማያ ገጽ ለማጋራት መታ ያድርጉ ወይም ቅጽበታዊ ማያ ገጹ እስኪጨርስ ይጠብቁ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"የሳንካ ሪፖርቶች የግል መረጃን ጨምሮ ከበርካታ የስርዓቱ ምዝግብ ማስታወሻዎች የመጣ ውሂብን ይዟል። የሳንካ ሪፖርቶች ለሚያምኗቸው መተግበሪያዎችን እና ሰዎችን ብቻ ያጋሩ።"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ይህን መልዕክት በሚቀጥለው ጊዜ አሳይ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"የሳንካ ሪፖርቶች"</string>
diff --git a/packages/Shell/res/values-ar/strings.xml b/packages/Shell/res/values-ar/strings.xml
index f0af8ce..818c368 100644
--- a/packages/Shell/res/values-ar/strings.xml
+++ b/packages/Shell/res/values-ar/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"جارٍ إنشاء تقرير الخطأ <xliff:g id="ID">#%d</xliff:g>."</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"تم تسجيل تقرير الخطأ <xliff:g id="ID">#%d</xliff:g>."</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"تم التقاط تقرير الأخطاء <xliff:g id="ID">#%d</xliff:g> ولكن في انتظار لقطة الشاشة"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"إضافة تفاصيل إلى تقرير الخطأ"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"الرجاء الانتظار…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"مرر بسرعة لليمين لمشاركة تقرير الخطأ"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"انقر لمشاركة تقرير الخطأ."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"انقر لمشاركة تقرير الأخطاء بدون لقطة شاشة أو انتظر حتى انتهاء لقطة الشاشة"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"انقر لمشاركة تقرير الأخطاء بدون لقطة شاشة أو انتظر حتى انتهاء لقطة الشاشة"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"تحتوي تقارير الأخطاء على بيانات من ملفات سجلات النظام المتنوعة، بما في ذلك معلومات شخصية وخاصة. لا تشارك تقارير الأخطاء إلا مع التطبيقات والأشخاص الموثوق بهم."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"إظهار هذه الرسالة في المرة القادمة"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"تقارير الأخطاء"</string>
diff --git a/packages/Shell/res/values-az-rAZ/strings.xml b/packages/Shell/res/values-az-rAZ/strings.xml
index 6d375fe..22791a6 100644
--- a/packages/Shell/res/values-az-rAZ/strings.xml
+++ b/packages/Shell/res/values-az-rAZ/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Baq hesabatı <xliff:g id="ID">#%d</xliff:g> yaradıldı"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Baq hesabatı <xliff:g id="ID">#%d</xliff:g> alındı"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"<xliff:g id="ID">#%d</xliff:g> baq hesabatı çəkildi, amma skrinşot hələ gözlənilir"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Detallar baq hesabatına əlavə olunur"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Lütfən, gözləyin..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Baq raportunu paylaşmaq üçün sola sürüşdürün"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Baq hesabatınızı paylaşmaq üçün tıklayın"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"baq hesabatınızı skrinşot olmadan paylaşmaq üçün tıklayın, skrinşotun tamamlanması üçün isə gözləyin"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"baq hesabatınızı skrinşot olmadan paylaşmaq üçün tıklayın, skrinşotun tamamlanması üçün isə gözləyin"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Baq raportları sistemin müxtəlif jurnal fayllarından data içərir ki, buna şəxsi və konfidensial məlumatlar da aiddir. Yalnız inandığınız adamlarla baq raportlarını paylaşın."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Bu mesajı növbəti dəfə göstər"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Baq hesabatları"</string>
diff --git a/packages/Shell/res/values-b+sr+Latn/strings.xml b/packages/Shell/res/values-b+sr+Latn/strings.xml
index ad84941..bc5ce26 100644
--- a/packages/Shell/res/values-b+sr+Latn/strings.xml
+++ b/packages/Shell/res/values-b+sr+Latn/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Izveštaj o grešci <xliff:g id="ID">#%d</xliff:g> se generiše"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Izveštaj o grešci <xliff:g id="ID">#%d</xliff:g> je snimljen"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Izveštaj o grešci <xliff:g id="ID">#%d</xliff:g> snimljen; snimak ekrana se čeka"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodaju se detalji u izveštaj o grešci"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Sačekajte..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Prevucite ulevo da biste delili izveštaj o greškama"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Dodirnite da biste delili izveštaj o grešci"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Dodirnite za deljenje izveštaja o grešci bez snimka ekrana ili sačekajte da se napravi snimak ekrana"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Dodirnite za deljenje izveštaja o grešci bez snimka ekrana ili sačekajte da se napravi snimak ekrana"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Izveštaji o greškama sadrže podatke iz različitih sistemskih datoteka evidencije, uključujući lične i privatne podatke. Delite izveštaje o greškama samo sa aplikacijama i ljudima u koje imate poverenja."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Prikaži ovu poruku sledeći put"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Izveštaji o greškama"</string>
diff --git a/packages/Shell/res/values-bg/strings.xml b/packages/Shell/res/values-bg/strings.xml
index e543839..0f8676f 100644
--- a/packages/Shell/res/values-bg/strings.xml
+++ b/packages/Shell/res/values-bg/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Команден ред"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Сигналът за програмна грешка „<xliff:g id="ID">#%d</xliff:g>“ се генерира"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Сигналът за програмна грешка „<xliff:g id="ID">#%d</xliff:g>“ е заснет"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Сигналът (<xliff:g id="ID">#%d</xliff:g>) е заснет, но екр. снимка не е готова"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Подробностите се добавят към сигнала за пр. грешка"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Моля, изчакайте…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Прекарайте пръст наляво, за да споделите сигнала си за програмна грешка"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Докоснете, за да споделите сигнала си за програмна грешка"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Докоснете, за да споделите сигнала за прогр. грешка без екранна снимка, или изчакайте завършването й"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Докоснете, за да споделите сигнала за прогр. грешка без екранна снимка, или изчакайте завършването й"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Отчетите за програмни грешки съдържат данни от различни регистрационни файлове на системата, включително лична и поверителна информация. Споделяйте ги само с приложения и хора, на които имате доверие."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Това съобщение да се показва следващия път"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Отчети за прогр. грешки"</string>
diff --git a/packages/Shell/res/values-bn-rBD/strings.xml b/packages/Shell/res/values-bn-rBD/strings.xml
index bba778d..c632b10 100644
--- a/packages/Shell/res/values-bn-rBD/strings.xml
+++ b/packages/Shell/res/values-bn-rBD/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"শেল"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ত্রুটির প্রতিবেদন <xliff:g id="ID">#%d</xliff:g> তৈরি করা হচ্ছে"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ত্রুটির প্রতিবেদন <xliff:g id="ID">#%d</xliff:g> ক্যাপচার করা হয়েছে"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ত্রুটির প্রতিবেদন <xliff:g id="ID">#%d</xliff:g> ক্যাপচার করা হয়েছে কিন্তু স্ক্রীনশট নেওয়ার কাজ সম্পন্ন হয়নি"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ত্রুটির প্রতিবেদনে বিশদ বিবরণ যোগ করা হচ্ছে"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"অনুগ্রহ করে অপেক্ষা করুন..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"আপনার বাগ রিপোর্ট শেয়ার করতে বামে সোয়াইপ করুন"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"আপনার ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"কোনো স্ক্রীনশট ছাড়াই ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন বা সম্পন্ন করতে স্ক্রীনশটের জন্য অপেক্ষা করুন"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"কোনো স্ক্রীনশট ছাড়াই ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন বা সম্পন্ন করতে স্ক্রীনশটের জন্য অপেক্ষা করুন"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ত্রুটির প্রতিবেদনগুলিতে থাকা ডেটা, সিস্টেমের বিভিন্ন লগ ফাইলগুলি থেকে আসে, যাতে ব্যক্তিগত এবং গোপনীয় তথ্য অন্তর্ভুক্ত থাকে৷ আপনি বিশ্বাস করেন শুধুমাত্র এমন অ্যাপ্লিকেশান এবং ব্যক্তিদের সাথে ত্রুটির প্রতিবেদনগুলি ভাগ করুন৷"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"এই বার্তাটি পরের বার দেখান"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ত্রুটির প্রতিবেদনগুলি"</string>
diff --git a/packages/Shell/res/values-bs-rBA/strings.xml b/packages/Shell/res/values-bs-rBA/strings.xml
index 54be955..f4d71e9 100644
--- a/packages/Shell/res/values-bs-rBA/strings.xml
+++ b/packages/Shell/res/values-bs-rBA/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Ljuska"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Izvještaj o grešci <xliff:g id="ID">#%d</xliff:g> se generira"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Izvještaj o grešci <xliff:g id="ID">#%d</xliff:g> je snimljen"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Izvještaj o greškama <xliff:g id="ID">#%d</xliff:g> snimljen, čeka se snim. ekr."</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodavanje detalja u izvještaj o greškama"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Pričekajte..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Prevucite lijevo da podijelite izvještaj o greškama"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Dodirnite da biste podijelili izvještaj o grešci"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Dodirnite da podijelite izveštaj o greškama bez snimka ekrana ili sačekajte da snimak bude gotov"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Dodirnite da podijelite izveštaj o greškama bez snimka ekrana ili sačekajte da snimak bude gotov"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Izvještaji o greškama sadrže podatke iz raznih zapisnika sistema, uključujući lične i privatne informacije. Podijelite izvještaje o greškama samo sa aplikacijama i osobama kojima vjerujete."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Pokaži ovu poruku sljedeći put"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Izvještaji o greškama"</string>
diff --git a/packages/Shell/res/values-ca/strings.xml b/packages/Shell/res/values-ca/strings.xml
index a92177e..3efb53b 100644
--- a/packages/Shell/res/values-ca/strings.xml
+++ b/packages/Shell/res/values-ca/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Protecció"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"S\'està generant l\'informe d\'errors <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"S\'ha capturat l\'informe d\'errors <xliff:g id="ID">#%d</xliff:g>"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"L\'informe d\'errors <xliff:g id="ID">#%d</xliff:g> s\'ha capturat (captura pendent)"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"S\'estan afegint detalls a l\'informe d\'errors"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Espera…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Llisca cap a l\'esquerra per compartir l\'informe d\'errors."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toca per compartir l\'informe d\'errors"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toca per compartir l\'informe d\'errors sense captura de pantalla o espera que es creï la captura"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toca per compartir l\'informe d\'errors sense captura de pantalla o espera que es creï la captura"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Els informes d\'error contenen dades dels diferents fitxers de registre del sistema, inclosa informació privada i personal. Comparteix els informes d\'error només amb les aplicacions i amb les persones en qui confies."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostra aquest missatge la propera vegada"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes d\'error"</string>
diff --git a/packages/Shell/res/values-cs/strings.xml b/packages/Shell/res/values-cs/strings.xml
index 6f7549a..afb6f9e 100644
--- a/packages/Shell/res/values-cs/strings.xml
+++ b/packages/Shell/res/values-cs/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Zpráva o chybě <xliff:g id="ID">#%d</xliff:g> se vytváří"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Zpráva o chybě <xliff:g id="ID">#%d</xliff:g> byla vytvořena"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Zpráva o chybě <xliff:g id="ID">#%d</xliff:g> byla vytvořena, čeká se na snímek"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Přidávání podrobností do zprávy o chybě"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Čekejte prosím…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Chcete-li hlášení chyby sdílet, přejeďte doleva."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Zprávu o chybě můžete sdílet klepnutím"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Klepnutím můžete zprávu o chybě sdílet bez snímku obrazovky, nebo vyčkejte, než se snímek připraví"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Klepnutím můžete zprávu o chybě sdílet bez snímku obrazovky, nebo vyčkejte, než se snímek připraví"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Chybová hlášení obsahují data z různých souborů protokolů systému včetně osobních a soukromých informací. Chybová hlášení sdílejte pouze s aplikacemi a uživateli, kterým důvěřujete."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Zobrazit tuto zprávu příště"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Zprávy o chybách"</string>
diff --git a/packages/Shell/res/values-da/strings.xml b/packages/Shell/res/values-da/strings.xml
index 72a9a99..0f7b784 100644
--- a/packages/Shell/res/values-da/strings.xml
+++ b/packages/Shell/res/values-da/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Fejlrapporten <xliff:g id="ID">#%d</xliff:g> genereres"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Fejrapporten <xliff:g id="ID">#%d</xliff:g> blev gemt"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Fejlrapport <xliff:g id="ID">#%d</xliff:g> blev gemt, men skærmbilledet afventer"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Tilføjelse af oplysninger til fejlrapporten"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Vent et øjeblik…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Stryg til venstre for at dele din fejlrapport"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tryk for at dele din fejlrapport"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tryk for at dele din fejlrapport uden et skærmbillede, eller vent på, at skærmbilledet fuldføres"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tryk for at dele din fejlrapport uden et skærmbillede, eller vent på, at skærmbilledet fuldføres"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Fejlrapporter indeholder data fra systemets forskellige logfiler, f.eks. personlige og private oplysninger. Del kun fejlrapporter med apps og personer, du har tillid til."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Vis denne underretning næste gang"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Fejlrapporter"</string>
diff --git a/packages/Shell/res/values-de/strings.xml b/packages/Shell/res/values-de/strings.xml
index f848c9d..8f87fed 100644
--- a/packages/Shell/res/values-de/strings.xml
+++ b/packages/Shell/res/values-de/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Fehlerbericht <xliff:g id="ID">#%d</xliff:g> wird generiert"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Fehlerbericht <xliff:g id="ID">#%d</xliff:g> erfasst"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Fehlerbericht <xliff:g id="ID">#%d</xliff:g> erfasst, aber Screenshot ausstehend"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Informationen werden zum Fehlerbericht hinzugefügt"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Bitte warten…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Wische nach links, um deinen Fehlerbericht zu teilen."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Zum Teilen des Fehlerberichts tippen"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tippe, um den Fehlerbericht ohne Screenshot zu teilen, oder warte auf den Screenshot"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tippe, um den Fehlerbericht ohne Screenshot zu teilen, oder warte auf den Screenshot"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Fehlerberichte enthalten Daten aus verschiedenen Protokolldateien des Systems, darunter auch personenbezogene und private Daten. Teile Fehlerberichte nur mit Apps und Personen, denen du vertraust."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Diese Nachricht nächstes Mal zeigen"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Fehlerberichte"</string>
diff --git a/packages/Shell/res/values-el/strings.xml b/packages/Shell/res/values-el/strings.xml
index 0c04809..517d83a 100644
--- a/packages/Shell/res/values-el/strings.xml
+++ b/packages/Shell/res/values-el/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Κέλυφος"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Δημιουργείται η αναφορά σφάλματος <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Έγινε λήψη της αναφοράς σφάλματος <xliff:g id="ID">#%d</xliff:g>"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Η αναφ. σφάλματος <xliff:g id="ID">#%d</xliff:g> ελήφθη, αλλά το στιγμ. εκκρεμεί"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Προσθήκη λεπτομερειών στην αναφορά σφάλματος"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Περιμένετε…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Σύρετε προς τα αριστερά για κοινή χρήση της αναφοράς σφαλμάτων"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Πατήστε για κοινή χρήση της αναφοράς σφάλματος"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Πατήστε για κοινοποίηση της αναφοράς σφάλματος χωρίς στιγμιότυπο οθόνης ή περιμένετε να ολοκληρωθεί"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Πατήστε για κοινοποίηση της αναφοράς σφάλματος χωρίς στιγμιότυπο οθόνης ή περιμένετε να ολοκληρωθεί"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Οι αναφορές σφαλμάτων περιέχουν δεδομένα από τα διάφορα αρχεία καταγραφής του συστήματος, συμπεριλαμβανομένων προσωπικών και ιδιωτικών πληροφοριών. Να μοιράζεστε αναφορές σφαλμάτων μόνο με εφαρμογές και άτομα που εμπιστεύεστε."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Εμφάνιση αυτού του μηνύματος την επόμενη φορά"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Αναφορές σφαλμάτων"</string>
diff --git a/packages/Shell/res/values-en-rAU/strings.xml b/packages/Shell/res/values-en-rAU/strings.xml
index ad637f5..2349ec5 100644
--- a/packages/Shell/res/values-en-rAU/strings.xml
+++ b/packages/Shell/res/values-en-rAU/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Bug report <xliff:g id="ID">#%d</xliff:g> is being generated"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Bug report <xliff:g id="ID">#%d</xliff:g> captured"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Bug report <xliff:g id="ID">#%d</xliff:g> captured but screenshot pending"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Adding details to the bug report"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Please wait…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swipe left to share your bug report"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tap to share your bug report"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tap to share your bug report without a screenshot or wait for the screenshot to finish"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tap to share your bug report without a screenshot or wait for the screenshot to finish"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people that you trust."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Show this message next time"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Bug reports"</string>
diff --git a/packages/Shell/res/values-en-rGB/strings.xml b/packages/Shell/res/values-en-rGB/strings.xml
index ad637f5..2349ec5 100644
--- a/packages/Shell/res/values-en-rGB/strings.xml
+++ b/packages/Shell/res/values-en-rGB/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Bug report <xliff:g id="ID">#%d</xliff:g> is being generated"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Bug report <xliff:g id="ID">#%d</xliff:g> captured"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Bug report <xliff:g id="ID">#%d</xliff:g> captured but screenshot pending"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Adding details to the bug report"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Please wait…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swipe left to share your bug report"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tap to share your bug report"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tap to share your bug report without a screenshot or wait for the screenshot to finish"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tap to share your bug report without a screenshot or wait for the screenshot to finish"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people that you trust."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Show this message next time"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Bug reports"</string>
diff --git a/packages/Shell/res/values-en-rIN/strings.xml b/packages/Shell/res/values-en-rIN/strings.xml
index ad637f5..2349ec5 100644
--- a/packages/Shell/res/values-en-rIN/strings.xml
+++ b/packages/Shell/res/values-en-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Bug report <xliff:g id="ID">#%d</xliff:g> is being generated"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Bug report <xliff:g id="ID">#%d</xliff:g> captured"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Bug report <xliff:g id="ID">#%d</xliff:g> captured but screenshot pending"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Adding details to the bug report"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Please wait…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swipe left to share your bug report"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tap to share your bug report"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tap to share your bug report without a screenshot or wait for the screenshot to finish"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tap to share your bug report without a screenshot or wait for the screenshot to finish"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people that you trust."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Show this message next time"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Bug reports"</string>
diff --git a/packages/Shell/res/values-es-rUS/strings.xml b/packages/Shell/res/values-es-rUS/strings.xml
index a9a1e08..307548a 100644
--- a/packages/Shell/res/values-es-rUS/strings.xml
+++ b/packages/Shell/res/values-es-rUS/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Se está generando el informe de errores <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Se capturó el informe de errores <xliff:g id="ID">#%d</xliff:g>"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Informe de errores <xliff:g id="ID">#%d</xliff:g> capturado (captura pendiente)"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Agregando detalles al informe de errores"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Espera…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Desliza el dedo hacia la izquierda para compartir el informe de errores."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toca para compartir el informe de errores"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toca para compartir tu informe de errores sin una captura de pantalla o espera a que finalice"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toca para compartir tu informe de errores sin una captura de pantalla o espera a que finalice"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Los informes de errores contienen datos de los distintos archivos de registro del sistema, incluida la información personal y privada. Comparte los informes de errores únicamente con aplicaciones y personas en las que confíes."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar este mensaje la próxima vez"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes de errores"</string>
diff --git a/packages/Shell/res/values-es/strings.xml b/packages/Shell/res/values-es/strings.xml
index b82d372..730ae73 100644
--- a/packages/Shell/res/values-es/strings.xml
+++ b/packages/Shell/res/values-es/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Se está generando el informe de errores <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Informe de errores <xliff:g id="ID">#%d</xliff:g> capturado"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Informe <xliff:g id="ID">#%d</xliff:g> registrado (captura pantalla pendiente)"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Añadiendo detalles al informe de errores"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Espera…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Desliza el dedo hacia la izquierda para compartir el informe de error"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toca para compartir el informe de errores"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toca para compartir el informe de errores sin captura de pantalla o espera a que se haga la captura."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toca para compartir el informe de errores sin captura de pantalla o espera a que se haga la captura."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Los informes de errores contienen datos de los distintos archivos de registro del sistema, incluida información personal y privada. Comparte los informes de errores únicamente con aplicaciones y usuarios en los que confíes."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar este mensaje la próxima vez"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes de error"</string>
diff --git a/packages/Shell/res/values-et-rEE/strings.xml b/packages/Shell/res/values-et-rEE/strings.xml
index cdb774a0..028e2bd 100644
--- a/packages/Shell/res/values-et-rEE/strings.xml
+++ b/packages/Shell/res/values-et-rEE/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Kest"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Luuakse veaaruannet <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Jäädvustati veaaruanne <xliff:g id="ID">#%d</xliff:g>"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Jäädvustati veaaruanne <xliff:g id="ID">#%d</xliff:g>, kuid ekraanipilt on ootel"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Üksikasjade lisamine veaaruandesse"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Oodake …"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Veaaruande jagamiseks pühkige vasakule"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Veaaruande jagamiseks puudutage"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Puudutage, et veaaruannet ilma ekraanipildita jagada, või oodake, kuni ekraanipilt tehtud saab."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Puudutage, et veaaruannet ilma ekraanipildita jagada, või oodake, kuni ekraanipilt tehtud saab."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Veaaruanded sisaldavad andmeid erinevatest süsteemi logifailidest, sh isiklikku ja privaatset teavet. Jagage veaaruandeid ainult usaldusväärsete rakenduste ja inimestega."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Kuva see sõnum järgmisel korral"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Veaaruanded"</string>
diff --git a/packages/Shell/res/values-eu-rES/strings.xml b/packages/Shell/res/values-eu-rES/strings.xml
index 42dfe27..7946f67 100644
--- a/packages/Shell/res/values-eu-rES/strings.xml
+++ b/packages/Shell/res/values-eu-rES/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell-interfazea"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Akatsen <xliff:g id="ID">#%d</xliff:g> txostena egiten ari gara"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Akatsen <xliff:g id="ID">#%d</xliff:g> txostena egin da"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Egin da <xliff:g id="ID">#%d</xliff:g> txostena. Pantaila-argazkia falta da."</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Akatsen txostenean xehetasunak gehitzen"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Itxaron, mesedez…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Programa-akatsen txostena partekatzeko, pasatu hatza ezkerrera"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Sakatu akatsen txostena partekatzeko"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Sakatu akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Sakatu akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Akatsen txostenek sistemaren erregistro-fitxategietako datuak dauzkate, informazio pertsonala eta pribatua barne. Akatsen txostenak partekatzen badituzu, partekatu soilik aplikazio eta pertsona fidagarriekin."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Erakutsi mezu hau hurrengoan"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Akatsen txostenak"</string>
diff --git a/packages/Shell/res/values-fa/strings.xml b/packages/Shell/res/values-fa/strings.xml
index e825f3a..ecadf1a 100644
--- a/packages/Shell/res/values-fa/strings.xml
+++ b/packages/Shell/res/values-fa/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"گزارش اشکال <xliff:g id="ID">#%d</xliff:g> در حال ایجاد شدن است"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"گزارش اشکال <xliff:g id="ID">#%d</xliff:g> ثبت شد"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"گزارش اشکال <xliff:g id="ID">#%d</xliff:g> گرفته شد اما عکس از صفحه‌نمایش هنوز نه"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"اضافه کردن جزئیات به گزارش اشکال"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"لطفاً منتظر بمانید..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"برای اشتراک‌گذاری گزارش اشکال، به تندی آن را به چپ بکشید"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"برای به اشتراک گذاشتن گزارش اشکال، ضربه بزنید"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"برای اشتراک‌گذاری گزارش مشکل بدون عکس صفحه‌نمایش، ضربه بزنید یا صبر کنید تا عکس صفحه‌نمایش گرفته شود."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"برای اشتراک‌گذاری گزارش مشکل بدون عکس صفحه‌نمایش، ضربه بزنید یا صبر کنید تا عکس صفحه‌نمایش گرفته شود."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"گزارش‌های اشکال حاوی داده‌هایی از فایل‌های گزارش مختلف در سیستم هستند، شامل اطلاعات شخصی و خصوصی. گزارش‌های اشکال را فقط با افراد و برنامه‌های مورد اعتماد خود به اشتراک بگذارید."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"دفعه بعد این پیام نشان داده شود"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"گزارش اشکال"</string>
diff --git a/packages/Shell/res/values-fi/strings.xml b/packages/Shell/res/values-fi/strings.xml
index 8c67c66..b5ae006 100644
--- a/packages/Shell/res/values-fi/strings.xml
+++ b/packages/Shell/res/values-fi/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Komentotulkki"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Luodaan virheraporttia <xliff:g id="ID">#%d</xliff:g>."</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Virheraportti <xliff:g id="ID">#%d</xliff:g> tallennettu"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Virheraportti <xliff:g id="ID">#%d</xliff:g> tallennettu, kuvakaappaus odottaa."</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Lisätään tietoja virheraporttiin"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Odota…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Jaa virheraportti pyyhkäisemällä vasemmalle"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Jaa virheraportti napauttamalla."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Jaa virheraportti ilman kuvakaappausta napauttamalla tai odota, että kuvakaappaus latautuu."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Jaa virheraportti ilman kuvakaappausta napauttamalla tai odota, että kuvakaappaus latautuu."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Virheraportit sisältävät järjestelmän lokitietoja, ja niihin voi sisältyä henkilökohtaisia ja yksityisiä tietoja. Jaa virheraportteja vain luotettaville sovelluksille ja käyttäjille."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Näytä tämä viesti seuraavalla kerralla"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Virheraportit"</string>
diff --git a/packages/Shell/res/values-fr-rCA/strings.xml b/packages/Shell/res/values-fr-rCA/strings.xml
index 3daa120..6c40edd 100644
--- a/packages/Shell/res/values-fr-rCA/strings.xml
+++ b/packages/Shell/res/values-fr-rCA/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Rapport de bogue <xliff:g id="ID">#%d</xliff:g> généré"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Rapport de bogue <xliff:g id="ID">#%d</xliff:g> enregistré"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Rap. bogue <xliff:g id="ID">#%d</xliff:g> enreg., mais attente de saisie d\'écran"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Ajout de détails au rapport de bogue"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Veuillez patienter…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Faites glisser le doigt vers la gauche pour partager votre rapport de bogue."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Touchez ici pour partager votre rapport de bogue"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Touchez pour partager le rapport de bogue sans saisie d\'écran ou attendez que la saisie soit prête"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Touchez pour partager le rapport de bogue sans saisie d\'écran ou attendez que la saisie soit prête"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Les rapports de bogue contiennent des données des fichiers journaux du système, y compris des informations personnelles et privées. Ne partagez les rapports de bogue qu\'avec les applications et les personnes que vous estimez fiables."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afficher ce message la prochaine fois"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapports de bogues"</string>
diff --git a/packages/Shell/res/values-fr/strings.xml b/packages/Shell/res/values-fr/strings.xml
index c512aca..54f0b98 100644
--- a/packages/Shell/res/values-fr/strings.xml
+++ b/packages/Shell/res/values-fr/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Le rapport de bug \"<xliff:g id="ID">#%d</xliff:g>\" est en cours de création"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Le rapport de bug \"<xliff:g id="ID">#%d</xliff:g>\" a bien été enregistré"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Rapport bug \"<xliff:g id="ID">#%d</xliff:g>\" enregistré, mais attente capt. écran"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Ajout d\'informations au rapport de bug"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Veuillez patienter…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Faites glisser le doigt vers la gauche pour partager votre rapport d\'erreur."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Appuyer pour partager votre rapport de bug"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Appuyer pour partager rapport de bug sans capture d\'écran ou attendre finalisation capture d\'écran"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Appuyer pour partager rapport de bug sans capture d\'écran ou attendre finalisation capture d\'écran"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Les rapports de bug contiennent des données des fichiers journaux du système, y compris des informations personnelles et privées. Ne partagez les rapports de bug qu\'avec les applications et les personnes que vous estimez fiables."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afficher ce message la prochaine fois"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapports d\'erreur"</string>
diff --git a/packages/Shell/res/values-gl-rES/strings.xml b/packages/Shell/res/values-gl-rES/strings.xml
index ea95c97..d4610977b 100644
--- a/packages/Shell/res/values-gl-rES/strings.xml
+++ b/packages/Shell/res/values-gl-rES/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Estase xerando o informe de erros <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Rexistrouse o informe de erros <xliff:g id="ID">#%d</xliff:g>"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Inf. erros <xliff:g id="ID">#%d</xliff:g> rexistrado e captura pantalla pendente"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Engadindo detalles ao informe de erro"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Agarda..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Pasa o dedo á esquerda para compartir o teu informe de erros"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toca para compartir o teu informe de erros"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toca para compartir o informe de erros sen captura de pantalla ou agarda a que finalice a captura"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toca para compartir o informe de erros sen captura de pantalla ou agarda a que finalice a captura"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os informes de erros conteñen datos dos distintos ficheiros de rexistro do sistema, incluída información persoal e privada. Comparte os informes de erros unicamente con aplicacións e persoas de confianza."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensaxe a próxima vez"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes de erros"</string>
diff --git a/packages/Shell/res/values-gu-rIN/strings.xml b/packages/Shell/res/values-gu-rIN/strings.xml
index 1436c3d..f99167d 100644
--- a/packages/Shell/res/values-gu-rIN/strings.xml
+++ b/packages/Shell/res/values-gu-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"શેલ"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"બગ રિપોર્ટ <xliff:g id="ID">#%d</xliff:g> જનરેટ કરવામાં આવી રહી છે"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"બગ રિપોર્ટ <xliff:g id="ID">#%d</xliff:g> કૅપ્ચર કરી"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"બગ રિપોર્ટ <xliff:g id="ID">#%d</xliff:g> કૅપ્ચર કરી પરંતુ સ્ક્રીનશૉટ બાકી છે"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"બગ રિપોર્ટમાં વિગતો ઉમેરવી"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"કૃપા કરીને રાહ જુઓ…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"તમારી બગ રિપોર્ટ શેર કરવા માટે ડાબે સ્વાઇપ કરો"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"તમારી બગ રિપોર્ટ શેર કરવા ટૅપ કરો"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"સ્ક્રીનશૉટ વગર અથવા સ્ક્રીનશૉટ સમાપ્ત થવાની રાહ જોયા વગર તમારી બગ રિપોર્ટ શેર કરવા ટૅપ કરો"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"સ્ક્રીનશૉટ વગર અથવા સ્ક્રીનશૉટ સમાપ્ત થવાની રાહ જોયા વગર તમારી બગ રિપોર્ટ શેર કરવા ટૅપ કરો"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"બગ રિપોર્ટ્સ વ્યક્તિગત અને ખાનગી માહિતી સહિત, સિસ્ટમની વિભિન્ન લૉગ ફાઇલોનો ડેટા ધરાવે છે. બગ રિપોર્ટ્સ ફક્ત તમે વિશ્વાસ કરતા હો તે એપ્લિકેશનો અને લોકો સાથે જ શેર કરો."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"આગલી વખતે આ સંદેશ બતાવો"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"બગ રિપોર્ટ્સ"</string>
diff --git a/packages/Shell/res/values-hi/strings.xml b/packages/Shell/res/values-hi/strings.xml
index 9a735f2..aedec04 100644
--- a/packages/Shell/res/values-hi/strings.xml
+++ b/packages/Shell/res/values-hi/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"शेल"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g> जेनरेट की जा रही है"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g> कैप्चर की गई"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g> कैप्चर की गई लेकिन स्क्रीनशॉट लंबित है"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"बग रिपोर्ट में विवरण जोड़े जा रहे हैं"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"कृपया प्रतीक्षा करें…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"अपनी बग रिपोर्ट साझा करने के लिए बाएं स्वाइप करें"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"अपनी बग रिपोर्ट साझा करने के लिए टैप करें"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"अपनी बग रिपोर्ट को बिना स्क्रीनशॉट साझा करने हेतु टैप करें या स्क्रीनशॉट पूरा होने की प्रतीक्षा करें"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"अपनी बग रिपोर्ट को बिना स्क्रीनशॉट साझा करने हेतु टैप करें या स्क्रीनशॉट पूरा होने की प्रतीक्षा करें"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"बग रिपोर्ट में व्यक्तिगत और निजी जानकारी सहित, सिस्टम की विभिन्न लॉग फ़ाइलों का डेटा होता है. बग रिपोर्ट केवल विश्वसनीय ऐप्स  और व्यक्तियों से ही साझा करें."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"यह संदेश अगली बार दिखाएं"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"बग रिपोर्ट"</string>
diff --git a/packages/Shell/res/values-hr/strings.xml b/packages/Shell/res/values-hr/strings.xml
index 71d50b8..462eb2a1 100644
--- a/packages/Shell/res/values-hr/strings.xml
+++ b/packages/Shell/res/values-hr/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Ljuska"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Generira se izvješće o programskoj pogrešci <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Izvješće o programskoj pogrešci <xliff:g id="ID">#%d</xliff:g> snimljeno"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Izvješće o pogrešci <xliff:g id="ID">#%d</xliff:g> snimljeno, ali se čeka snimka"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodavanje pojedinosti u izvješće o progr. pogrešci"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Pričekajte..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Prijeđite prstom ulijevo da biste poslali izvješće o programskim pogreškama"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Dodirnite da biste podijelili izvješće o programskoj pogrešci"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Dodirnite za dijeljenje izvješća o pogrešci bez snimke zaslona ili pričekajte da se izradi snimka"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Dodirnite za dijeljenje izvješća o pogrešci bez snimke zaslona ili pričekajte da se izradi snimka"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Prijave programskih pogrešaka sadržavaju podatke iz različitih datoteka zapisnika sustava, uključujući osobne i privatne informacije. Prijave programskih pogrešaka dijelite samo s aplikacijama i osobama koje smatrate pouzdanima."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Prikaži tu poruku sljedeći put"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Izvj. o prog. pogreš."</string>
diff --git a/packages/Shell/res/values-hu/strings.xml b/packages/Shell/res/values-hu/strings.xml
index cf10315..1f7f1fa 100644
--- a/packages/Shell/res/values-hu/strings.xml
+++ b/packages/Shell/res/values-hu/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Héj"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Hibajelentés (<xliff:g id="ID">#%d</xliff:g>) létrehozása folyamatban"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Hibajelentés (<xliff:g id="ID">#%d</xliff:g>) rögzítve"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Hibajelentés (<xliff:g id="ID">#%d</xliff:g>) rögzítve – képernyőkép függőben"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Információk hozzáadása a hibajelentéshez"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Kérjük, várjon..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Húzza ujját balra a hibajelentés megosztásához"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Koppintson a hibajelentés megosztásához"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Koppintson ide, ha képernyőkép nélkül osztaná meg a hibajelentést, vagy várjon a képernyőképre."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Koppintson ide, ha képernyőkép nélkül osztaná meg a hibajelentést, vagy várjon a képernyőképre."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"A programhiba-jelentések a rendszer különféle naplófájljaiból származó adatokat tartalmaznak, köztük személyes és magánjellegű információkat is. Csak olyan alkalmazásokkal és személyekkel osszon meg programhiba-jelentéseket, amelyekben vagy akikben megbízik."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Üzenet mutatása legközelebb"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Hibajelentések"</string>
diff --git a/packages/Shell/res/values-hy-rAM/strings.xml b/packages/Shell/res/values-hy-rAM/strings.xml
index 1cf5c94..c9351c2 100644
--- a/packages/Shell/res/values-hy-rAM/strings.xml
+++ b/packages/Shell/res/values-hy-rAM/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Խեցի"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"<xliff:g id="ID">#%d</xliff:g> վրիպակի զեկույցը ստեղծվում է"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"<xliff:g id="ID">#%d</xliff:g> վրիպակի զեկույցը գրանցվեց"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"<xliff:g id="ID">#%d</xliff:g> վրիպակի զեկույցը ստեղծվել է, սակայն էկրանի պատկերը դեռ չի ստացվել"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Տվյալների ավելացում վրիպակի զեկույցում"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Խնդրում ենք սպասել…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Սահեցրեք ձախ՝ սխալի հաշվետվությունը համօգտագործելու համար"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Հպեք՝ վրիպակի զեկույցը տրամադրելու համար"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Հպեք՝ վրիպակի զեկույցն առանց էկրանի պատկերի ուղարկելու համար կամ սպասեք էկրանի պատկերի ստեղծմանը"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Հպեք՝ վրիպակի զեկույցն առանց էկրանի պատկերի ուղարկելու համար կամ սպասեք էկրանի պատկերի ստեղծմանը"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Վրիպակի զեկույցները պարունակում են տվյալներ համակարգի տարբեր մուտքի ֆայլերից, այդ թվում նաև անհատական ​​և գաղտնի տեղեկություններ: Վրիպակի զեկույցները կիսեք միայն այն հավելվածների և մարդկանց հետ, որոնց վստահում եք:"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Այս հաղորդագրությունը ցույց տալ հաջորդ անգամ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Վրիպակների հաշվետվություններ"</string>
diff --git a/packages/Shell/res/values-in/strings.xml b/packages/Shell/res/values-in/strings.xml
index 1e8fe87..4bca166 100644
--- a/packages/Shell/res/values-in/strings.xml
+++ b/packages/Shell/res/values-in/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Kerangka"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Laporan bug <xliff:g id="ID">#%d</xliff:g> sedang dibuat"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Laporan bug <xliff:g id="ID">#%d</xliff:g> dijepret"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Laporan bug <xliff:g id="ID">#%d</xliff:g> dijepret, tetapi tangkapan layar belum selesai"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Menambahkan detail ke laporan bug"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Harap tunggu..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Gesek ke kiri untuk membagikan laporan bug Anda"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Ketuk untuk membagikan laporan bug"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Ketuk untuk membagikan laporan bug tanpa tangkapan layar atau menunggu tangkapan layar selesai"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Ketuk untuk membagikan laporan bug tanpa tangkapan layar atau menunggu tangkapan layar selesai"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Laporan bug berisi data dari berbagai file log sistem, termasuk informasi pribadi dan rahasia. Hanya bagikan laporan bug dengan aplikasi dan orang yang Anda percaya."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Tampilkan pesan ini lain kali"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Laporan bug"</string>
diff --git a/packages/Shell/res/values-is-rIS/strings.xml b/packages/Shell/res/values-is-rIS/strings.xml
index afcea59..aedf3bc3 100644
--- a/packages/Shell/res/values-is-rIS/strings.xml
+++ b/packages/Shell/res/values-is-rIS/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Skipanalína"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Verið er að búa til villutilkynningu <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Villutilkynning <xliff:g id="ID">#%d</xliff:g> búin til"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Villuskýrsla <xliff:g id="ID">#%d</xliff:g> tilbúin en skjámynd í vinnslu"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Bætir upplýsingum við villutilkynningu"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Augnablik..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Strjúktu til vinstri til að deila villuskýrslunni"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Ýttu til að deila villutilkynningunni"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Ýttu til að deila villutilkynningunni án skjámyndar eða hinkraðu þangað til skjámyndin er tilbúin"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Ýttu til að deila villutilkynningunni án skjámyndar eða hinkraðu þangað til skjámyndin er tilbúin"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Villutilkynningar innihalda gögn úr hinum ýmsu annálsskrám kerfisins, þ. á m. persónuleg gögn og trúnaðarupplýsingar. Deildu villutilkynningum eingöngu með forritum og fólki sem þú treystir."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Sýna þessi skilaboð næst"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Villutilkynningar"</string>
diff --git a/packages/Shell/res/values-it/strings.xml b/packages/Shell/res/values-it/strings.xml
index d7ac9a5..5c4b8d3 100644
--- a/packages/Shell/res/values-it/strings.xml
+++ b/packages/Shell/res/values-it/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Generazione segnalazione di bug <xliff:g id="ID">#%d</xliff:g> in corso"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Segnalazione di bug <xliff:g id="ID">#%d</xliff:g> acquisita"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Segnalazione bug <xliff:g id="ID">#%d</xliff:g> acquisita, screenshot in attesa"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Aggiunta di dettagli alla segnalazione di bug"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Attendi..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Scorri verso sinistra per condividere il rapporto sui bug"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tocca per condividere la segnalazione di bug"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tocca per inviare la segnalazione del bug senza screenshot o attendi che lo screenshot sia completo"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tocca per inviare la segnalazione del bug senza screenshot o attendi che lo screenshot sia completo"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Le segnalazioni di bug contengono dati da vari file di log del sistema, incluse informazioni personali e private. Condividi le segnalazioni di bug solo con app e persone attendibili."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostra questo messaggio la prossima volta"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapporti sui bug"</string>
diff --git a/packages/Shell/res/values-iw/strings.xml b/packages/Shell/res/values-iw/strings.xml
index fd64ee1..6589c8b 100644
--- a/packages/Shell/res/values-iw/strings.xml
+++ b/packages/Shell/res/values-iw/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"מעטפת"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"יצירת הדוח על הבאג <xliff:g id="ID">#%d</xliff:g> מתבצעת"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"הדוח על הבאג <xliff:g id="ID">#%d</xliff:g> צולם"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"הדוח על הבאג <xliff:g id="ID">#%d</xliff:g> נוצר, אך צילום המסך בהמתנה"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"מוסיף פרטים לדוח על הבאג"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"המתן…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"החלק שמאלה כדי לשתף את דוח הבאגים"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"הקש כדי לשתף את הדוח על הבאג"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"הקש כדי לשתף את הדוח על הבאג ללא צילום מסך, או המתן להשלמת צילום המסך"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"הקש כדי לשתף את הדוח על הבאג ללא צילום מסך, או המתן להשלמת צילום המסך"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"דוחות על באגים כוללים נתונים מקובצי היומן השונים במערכת, כולל מידע אישי ופרטי. שתף דוחות באגים רק עם אפליקציות ואנשים שאתה סומך עליהם."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"הצג את ההודעה הזו בפעם הבאה"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"דוחות באגים"</string>
diff --git a/packages/Shell/res/values-ja/strings.xml b/packages/Shell/res/values-ja/strings.xml
index 050c5df..a6ff33e 100644
--- a/packages/Shell/res/values-ja/strings.xml
+++ b/packages/Shell/res/values-ja/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"シェル"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"バグレポート <xliff:g id="ID">#%d</xliff:g> の生成中"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"バグレポート <xliff:g id="ID">#%d</xliff:g> の記録完了"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"バグレポート <xliff:g id="ID">#%d</xliff:g> 記録完了: スクリーンショット待ち"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"バグレポートに詳細情報を追加しています"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"お待ちください…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"バグレポートを共有するには左にスワイプ"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"バグレポートを共有するにはタップします"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"タップしてバグレポートをスクリーンショットなしで共有するか、スクリーンショット完成までお待ちください"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"タップしてバグレポートをスクリーンショットなしで共有するか、スクリーンショット完成までお待ちください"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"バグレポートには、個人の非公開情報など、システムのさまざまなログファイルのデータが含まれます。共有する場合は信頼するアプリとユーザーのみを選択してください。"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"このメッセージを次回も表示する"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"バグレポート"</string>
diff --git a/packages/Shell/res/values-ka-rGE/strings.xml b/packages/Shell/res/values-ka-rGE/strings.xml
index 8c5c6fb..119c360 100644
--- a/packages/Shell/res/values-ka-rGE/strings.xml
+++ b/packages/Shell/res/values-ka-rGE/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"გარეკანი"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ხარვეზების შესახებ ანგარიში <xliff:g id="ID">#%d</xliff:g> გენერირდება"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ხარვეზების შესახებ ანგარიში <xliff:g id="ID">#%d</xliff:g> აღბეჭდილია"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ხარვეზის ანგარიში <xliff:g id="ID">#%d</xliff:g> მზადაა. იქმნება ეკრანის ანაბეჭდი"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ხარვეზის შესახებ ანგარიშს დეტალები ემატება"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"გთხოვთ, მოითმინოთ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"გაასრიალეთ მარცხნივ თქვენი ხარვეზის შეტყობინების გასაზიარებლად"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"შეეხეთ ხარვეზების შესახებ ანგარიშის გასაზიარებლად"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"შეეხეთ ხარვეზის შესახებ ანგარიშის ეკრანის ანაბეჭდის გარეშე გასაზიარებლად, ან დაელოდეთ მის შექმნას"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"შეეხეთ ხარვეზის შესახებ ანგარიშის ეკრანის ანაბეჭდის გარეშე გასაზიარებლად, ან დაელოდეთ მის შექმნას"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ხარვეზის ანგარიშები მოიცავს მონაცემებს სხვადასხვა სისტემური ჟურნალის ფაილებიდან, მათ შორის პირად და კონფიდენციალურ ინფორმაციას."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"შემდგომში აჩვენე ეს შეტყობინება"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"შეცდომების ანგარიშები"</string>
diff --git a/packages/Shell/res/values-kk-rKZ/strings.xml b/packages/Shell/res/values-kk-rKZ/strings.xml
index edb2dd0..90028ca 100644
--- a/packages/Shell/res/values-kk-rKZ/strings.xml
+++ b/packages/Shell/res/values-kk-rKZ/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Қабыршық"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"<xliff:g id="ID">#%d</xliff:g> қате туралы есебі жасалуда"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"<xliff:g id="ID">#%d</xliff:g> қате туралы есебі жазып алынды"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"<xliff:g id="ID">#%d</xliff:g> қате туралы есебі жазып алынды, бірақ скриншот әлі сақталған жоқ"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Қате туралы есепке мәліметтер қосылуда"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Күте тұрыңыз…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Қате туралы есепті бөлісу үшін солға жанаңыз"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Қате туралы есепті бөлісу үшін түртіңіз"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Қате туралы есепті скриншотсыз бөлісу үшін түртіңіз немесе скриншот сақталып болғанша күтіңіз"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Қате туралы есепті скриншотсыз бөлісу үшін түртіңіз немесе скриншот сақталып болғанша күтіңіз"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Вирус туралы баянатта жүйеде тіркелген әртүрлі файлдар туралы деректер болады, оған жеке және құпия ақпарат та кіреді. Вирус баянаттарын сенімді қолданбалар және сенімді адамдармен ғана бөлісіңіз."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Бұл хабарды келесі жолы көрсетіңіз"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Қате туралы баяндамалар"</string>
diff --git a/packages/Shell/res/values-km-rKH/strings.xml b/packages/Shell/res/values-km-rKH/strings.xml
index ba0de9f..d5fc400 100644
--- a/packages/Shell/res/values-km-rKH/strings.xml
+++ b/packages/Shell/res/values-km-rKH/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"សែល"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"<xliff:g id="ID">#%d</xliff:g> របាយការណ៍កំហុសកំពុងត្រូវបានបង្កើត"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"<xliff:g id="ID">#%d</xliff:g> របាយការណ៍កំហុសត្រូវបានថត"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"<xliff:g id="ID">#%d</xliff:g> របាយការណ៍កំហុសត្រូវបានថត ប៉ុន្តែរូបថតអេក្រង់មិនទាន់បានថតនៅឡើយទេ"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"កំពុងបន្ថែមព័ត៌មានលម្អិតទៅរបាយការណ៍កំហុស"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"សូម​រង់ចាំ…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"អូស​ទៅ​ឆ្វេង​​ ដើម្បី​ចែក​រំលែក​របាយការណ៍​កំហុស​របស់​អ្នក"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"ប៉ះដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នក"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ប៉ះដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នកដោយមិនចាំបាច់មានរូបថតអេក្រង់ ឬរង់ចាំការបញ្ចប់ការថតអេក្រង់"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ប៉ះដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នកដោយមិនចាំបាច់មានរូបថតអេក្រង់ ឬរង់ចាំការបញ្ចប់ការថតអេក្រង់"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"របាយការណ៍​កំហុស​រួមមាន​ឯកសារ​កំណត់​ហេតុ​ផ្សេងៗ​របស់​ប្រព័ន្ធ រួមមាន​ព័ត៌មាន​ផ្ទាល់ខ្លួន និង​ឯកជន។ ចែករំលែក​របាយការណ៍​កំហុស​ជា​មួយ​កម្មវិធី និង​មនុស្ស​ដែល​អ្នក​ទុក​ចិត្ត។"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"បង្ហាញ​សារ​នេះ​ពេល​ក្រោយ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"រាយការណ៍ពីកំហុស"</string>
diff --git a/packages/Shell/res/values-kn-rIN/strings.xml b/packages/Shell/res/values-kn-rIN/strings.xml
index b041f35..1331f7e 100644
--- a/packages/Shell/res/values-kn-rIN/strings.xml
+++ b/packages/Shell/res/values-kn-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"ಶೆಲ್"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ದೋಷ ವರದಿಯ <xliff:g id="ID">#%d</xliff:g> ಅನ್ನು ರಚಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ದೋಷ ವರದಿಯ <xliff:g id="ID">#%d</xliff:g> ಅನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿಕೊಳ್ಳಲಾಗಿದೆ"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ದೋಷ ವರದಿಯ <xliff:g id="ID">#%d</xliff:g> ಅನ್ನು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿಕೊಳ್ಳಲಾಗಿದೆ ಆದರೆ ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಬಾಕಿ ಉಳಿದಿದೆ"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ಬಗ್ ವರದಿಗೆ ವಿವರಗಳನ್ನು ಸೇರಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"ದಯವಿಟ್ಟು ನಿರೀಕ್ಷಿಸಿ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"ನಿಮ್ಮ ದೋಷ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಎಡಕ್ಕೆ ಸ್ವೈಪ್‌ ಮಾಡಿ"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"ನಿಮ್ಮ ಬಗ್ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಇಲ್ಲದೇ ನಿಮ್ಮ ಬಗ್ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಟ್ಯಾಪ್ ಮಾಡಿ ಅಥವಾ ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಪೂರ್ತಿಯಾಗುವವರೆಗೂ ನಿರೀಕ್ಷಿಸಿ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಇಲ್ಲದೇ ನಿಮ್ಮ ಬಗ್ ವರದಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಟ್ಯಾಪ್ ಮಾಡಿ ಅಥವಾ ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಪೂರ್ತಿಯಾಗುವವರೆಗೂ ನಿರೀಕ್ಷಿಸಿ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ವೈಯಕ್ತಿಕ ಮತ್ತು ಖಾಸಗಿ ಮಾಹಿತಿಯು ಸೇರಿದಂತೆ, ಸಿಸ್ಟಂನ ಹಲವಾರು ಲಾಗ್ ಫೈಲ್‌ಗಳಿಂದ ಡೇಟಾವನ್ನು ದೋಷದ ವರದಿಗಳು ಒಳಗೊಂಡಿವೆ. ನೀವು ನಂಬುವಂತಹ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ಜನರೊಂದಿಗೆ ಮಾತ್ರ ದೋಷದ ವರದಿಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳಿ."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ಈ ಸಂದೇಶವನ್ನು ಮುಂದಿನ ಬಾರಿ ತೋರಿಸಿ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ದೋಷ ವರದಿಗಳು"</string>
diff --git a/packages/Shell/res/values-ko/strings.xml b/packages/Shell/res/values-ko/strings.xml
index 2a86360..4c0a169 100644
--- a/packages/Shell/res/values-ko/strings.xml
+++ b/packages/Shell/res/values-ko/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"셸"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"버그 신고 <xliff:g id="ID">#%d</xliff:g> 생성 중"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"버그 신고 <xliff:g id="ID">#%d</xliff:g> 캡처됨"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"버그 신고 <xliff:g id="ID">#%d</xliff:g>이(가) 캡처되었으나 스크린샷 대기 중"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"세부정보를 버그 보고서에 추가"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"잠시 기다려 주세요..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"왼쪽으로 스와이프하여 버그 신고서를 공유하세요."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"버그 신고를 공유하려면 탭하세요."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"스크린샷 없이 버그 신고서를 공유하려면 탭하고 그렇지 않으면 스크린샷이 완료될 때까지 기다려 주세요."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"스크린샷 없이 버그 신고서를 공유하려면 탭하고 그렇지 않으면 스크린샷이 완료될 때까지 기다려 주세요."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"버그 신고서는 시스템의 다양한 로그 파일 데이터(예: 개인 및 비공개 정보)를 포함합니다. 신뢰할 수 있는 앱과 사용자에게만 버그 신고서를 공유하세요."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"다음에 이 메시지 표시"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"버그 신고"</string>
diff --git a/packages/Shell/res/values-ky-rKG/strings.xml b/packages/Shell/res/values-ky-rKG/strings.xml
index c701b7e..16a9549 100644
--- a/packages/Shell/res/values-ky-rKG/strings.xml
+++ b/packages/Shell/res/values-ky-rKG/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Командалык кабык"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Мүчүлүштүк тууралуу билдирүү <xliff:g id="ID">#%d</xliff:g> түзүлүүдө"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Мүчүлүштүк тууралуу билдирүү <xliff:g id="ID">#%d</xliff:g> жаздырылды"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Мүчүлүштүк тууралуу билдирүү <xliff:g id="ID">#%d</xliff:g> даяр, скриншот күтүлүүдө"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Мүчүлүштүк жөнүндө кабардын чоо-жайы кошулууда"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Күтө туруңуз…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Ката жөнүндө кабар менен бөлүшүү үчүн солго серпип коюңуз"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Мүчүлүштүк тууралуу билдирүүңүздү бөлүшүү үчүн таптап коюңуз"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Мүчүлүштүк тууралуу билдирүүңүздү скриншотсуз бөлүшүү үчүн таптап коюңуз же скриншот даяр болгуча күтө туруңуз"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Мүчүлүштүк тууралуу билдирүүңүздү скриншотсуз бөлүшүү үчүн таптап коюңуз же скриншот даяр болгуча күтө туруңуз"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Ката тууралуу билдирүүлөр системанын ар кандай лог файлдарынын берилиштерин камтыйт, аларга өздүк жана купуя маалыматтар дагы кирет. Ката тууралуу билдирүүлөрдү сиз ишенген колдонмолор жана адамдар менен гана бөлүшүңүз."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Бул билдирүү кийин көрсөтүлсүн"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Мүчүлүштүктөрдү кабарлоолор"</string>
diff --git a/packages/Shell/res/values-lo-rLA/strings.xml b/packages/Shell/res/values-lo-rLA/strings.xml
index 4348250..2804528 100644
--- a/packages/Shell/res/values-lo-rLA/strings.xml
+++ b/packages/Shell/res/values-lo-rLA/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ກຳລັງສ້າງລາຍງານຂໍ້ຜິດພາດ <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ບັນທຶກລາຍງານຂໍ້ຜິດພາດ <xliff:g id="ID">#%d</xliff:g> ແລ້ວ"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ບັນທຶກລາຍງານຂໍ້ຜິດພາດ <xliff:g id="ID">#%d</xliff:g> ແລ້ວແຕ່ກຳລັງລໍຖ້າຮູບໜ້າຈໍຢູ່"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ກຳລັງເພີ່ມລາຍລະອຽດໃສ່ລາຍງານຂໍ້ຜິດພາດ"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"ກະລຸນາລໍຖ້າ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"​ປັດ​ໄປ​ຊ້າຍ​ເພື່ອ​ສົ່ງ​ລາຍ​ງານ​ຂໍ້​ຜິດ​ພາດ​ຂອງ​ທ່ານ"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"ແຕະເພື່ອແບ່ງປັນລາຍງານຂໍ້ຜິດພາດຂອງທ່ານ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ແຕະເພື່ອແບ່ງປັນລາຍງານຂໍ້ຜິດພາດຂອງທ່ານໂດຍບໍ່ໃຊ້ຮູບໜ້າຈໍ ຫຼື ລໍຖ້າໃຫ້ຮູບໜ້າຈໍແລ້ວໆ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ແຕະເພື່ອແບ່ງປັນລາຍງານຂໍ້ຜິດພາດຂອງທ່ານໂດຍບໍ່ໃຊ້ຮູບໜ້າຈໍ ຫຼື ລໍຖ້າໃຫ້ຮູບໜ້າຈໍແລ້ວໆ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ການລາຍງານຂໍ້ຜິດພາດປະກອບມີ ຂໍ້ມູນຈາກໄຟລ໌ບັນທຶກຂອງລະບົບຫຼາຍໄຟລ໌, ຮວມທັງຂໍ້ມູນສ່ວນໂຕນຳ. ທ່ານຕ້ອງແບ່ງປັນລາຍງານຂໍ້ຜິດພາດໃຫ້ແອັບຯ ແລະຄົນທີ່ທ່ານເຊື່ອຖືໄດ້ເທົ່ານັ້ນ."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ສະແດງຂໍ້ຄວາມນີ້ອີກໃນເທື່ອຕໍ່ໄປ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ລາຍ​ງານ​ບັນ​ຫາ"</string>
diff --git a/packages/Shell/res/values-lt/strings.xml b/packages/Shell/res/values-lt/strings.xml
index a714efc..a8468cf 100644
--- a/packages/Shell/res/values-lt/strings.xml
+++ b/packages/Shell/res/values-lt/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Apvalkalas"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Pranešimas apie riktą (<xliff:g id="ID">#%d</xliff:g>) generuojamas"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Pranešimas apie riktą (<xliff:g id="ID">#%d</xliff:g>) užfiksuotas"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Pranešimas apie riktą (<xliff:g id="ID">#%d</xliff:g>) užfiksuotas, bet laukiama ekrano kopijos"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Pridedama informacijos prie pranešimo apie riktą"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Palaukite…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Perbraukite kairėn, kad bendrintumėte rikto ataskaitą"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Palieskite, kad bendrintumėte pranešimą apie riktą"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Palieskite ir bendrinkite pranešimą apie riktą be ekrano kopijos arba palaukite, kol ji bus sukurta"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Palieskite ir bendrinkite pranešimą apie riktą be ekrano kopijos arba palaukite, kol ji bus sukurta"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Riktų ataskaitose pateikiami duomenys iš įvairių sistemos žurnalo failų, įskaitant asmeninę ir privačią informaciją. Riktų ataskaitas bendrinkite tik su patikimomis programomis ir žmonėmis."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Rodyti šį pranešimą kitą kartą"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Riktų ataskaitos"</string>
diff --git a/packages/Shell/res/values-lv/strings.xml b/packages/Shell/res/values-lv/strings.xml
index 880d651..08e25be 100644
--- a/packages/Shell/res/values-lv/strings.xml
+++ b/packages/Shell/res/values-lv/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Aizsargs"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Kļūdas pārskats <xliff:g id="ID">#%d</xliff:g> tiek ģenerēts"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Kļūdas pārskats <xliff:g id="ID">#%d</xliff:g> reģistrēts"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Kļūdas pārskats <xliff:g id="ID">#%d</xliff:g> izveidots; gaida ekrānuzņēmumu"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Informācijas pievienošana kļūdas pārskatam"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Lūdzu, uzgaidiet..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Velciet pa kreisi, lai kopīgotu savu kļūdu ziņojumu."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Pieskarieties, lai kopīgotu kļūdas pārskatu."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Pieskarieties, lai kopīgotu kļūdas pārskatu bez ekrānuzņēmuma vai gaidiet ekrānuzņēmumu."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Pieskarieties, lai kopīgotu kļūdas pārskatu bez ekrānuzņēmuma vai gaidiet ekrānuzņēmumu."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Kļūdu pārskatā ir iekļauti dati no dažādiem sistēmas žurnālfailiem, tostarp personas dati un privāta informācija. Kļūdu pārskatus ieteicams kopīgot tikai ar uzticamām lietotnēm un lietotājiem."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Rādīt šo ziņojumu nākamajā reizē"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Kļūdu ziņojumi"</string>
diff --git a/packages/Shell/res/values-mk-rMK/strings.xml b/packages/Shell/res/values-mk-rMK/strings.xml
index 478c189..3f879b7e 100644
--- a/packages/Shell/res/values-mk-rMK/strings.xml
+++ b/packages/Shell/res/values-mk-rMK/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Обвивка"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Се генерира извештајот за грешки <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Извештајот за грешки <xliff:g id="ID">#%d</xliff:g> е снимен"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Извештајот за грешка <xliff:g id="ID">#%d</xliff:g> е снимен. Се чека на сликата"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Се додаваат детали на извештајот за грешка"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Почекајте..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Повлечете налево за да споделите пријава за грешка"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Допрете за да го споделите извештајот за грешки"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Допрете за споделување извештај за грешки без слика од екранот или почекајте да се подготви сликата"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Допрете за споделување извештај за грешки без слика од екранот или почекајте да се подготви сликата"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Извештаите за грешка содржат податоци од разни датотеки за евиденција на системот, вклучувајќи лични и приватни информации. Извештаите за грешка споделувајте ги само со апликации и луѓе на коишто им верувате."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Прикажи ја поракава следниот пат"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Извештаи за грешки"</string>
diff --git a/packages/Shell/res/values-ml-rIN/strings.xml b/packages/Shell/res/values-ml-rIN/strings.xml
index 70e6333..3bb715d8 100644
--- a/packages/Shell/res/values-ml-rIN/strings.xml
+++ b/packages/Shell/res/values-ml-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"ഷെൽ"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ബഗ് റിപ്പോർട്ട് <xliff:g id="ID">#%d</xliff:g> സൃഷ്ടിക്കുന്നു"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ബഗ് റിപ്പോർട്ട് <xliff:g id="ID">#%d</xliff:g> ക്യാപ്ചർ ചെയ്തു"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ബഗ് റിപ്പോർട്ട് <xliff:g id="ID">#%d</xliff:g> ക്യാപ്ചർ ചെയ്തു, എന്നാൽ സ്ക്രീൻഷോട്ട് ശേഷിക്കുന്നു"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ബഗ് റിപ്പോർട്ടിലേക്ക് വിശദാംശങ്ങൾ ചേർക്കുന്നു"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"കാത്തിരിക്കുക..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടുന്നതിന് ഇടത്തേയ്‌ക്ക് സ്വൈപ്പുചെയ്യുക"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"സ്ക്രീൻഷോട്ട് കൂടാതെയോ സ്ക്രീൻഷോട്ട് പൂർത്തിയാകുന്നതിന് കാക്കാതെയോ നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"സ്ക്രീൻഷോട്ട് കൂടാതെയോ സ്ക്രീൻഷോട്ട് പൂർത്തിയാകുന്നതിന് കാക്കാതെയോ നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"വ്യക്തിഗതവും സ്വകാര്യവുമായ വിവരങ്ങൾ ഉൾപ്പെടെ, സിസ്റ്റത്തിന്റെ നിരവധി ലോഗ് ഫയലുകളിൽ നിന്നുള്ള ഡാറ്റ, ബഗ് റിപ്പോർട്ടുകളിൽ അടങ്ങിയിരിക്കുന്നു. നിങ്ങൾ വിശ്വസിക്കുന്ന അപ്ലിക്കേഷനുകൾക്കും ആളുകൾക്കും മാത്രം ബഗ് റിപ്പോർട്ടുകൾ പങ്കിടുക."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ഈ സന്ദേശം അടുത്ത തവണ ദൃശ്യമാക്കുക"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ബഗ് റിപ്പോർട്ടുകൾ"</string>
diff --git a/packages/Shell/res/values-mn-rMN/strings.xml b/packages/Shell/res/values-mn-rMN/strings.xml
index 49196a2..296afab 100644
--- a/packages/Shell/res/values-mn-rMN/strings.xml
+++ b/packages/Shell/res/values-mn-rMN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Шел"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Програмд гарсан алдааны мэдээллийн <xliff:g id="ID">#%d</xliff:g> үүсгэгдэж байна"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Програмд гарсан алдааны мэдээллийн <xliff:g id="ID">#%d</xliff:g>-г бүртгэгдлээ"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Алдааны тайлан <xliff:g id="ID">#%d</xliff:g>-г илрүүлсэн хэдий ч дэлгэцээс авсан зураг хүлээгдэж байна"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Алдааны тайланд дэлгэрэнгүй мэдээлэл нэмж байна"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Түр хүлээнэ үү..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Өөрийн согог репортыг хуваалцахын тулд зүүн шудрана уу"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Програмд гарсан алдааны мэдээллээ хуваалцах бол дарна уу"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Алдааны тайлангаа дэлгэцээс авсан зураггүйгээр хуваалцах бол дарж, эсвэл дэлгэцээс авсан зургийг бэлэн болтол нь хүлээнэ үү"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Алдааны тайлангаа дэлгэцээс авсан зураггүйгээр хуваалцах бол дарж, эсвэл дэлгэцээс авсан зургийг бэлэн болтол нь хүлээнэ үү"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Алдааны репорт нь хувийн болон нууц мэдээлэл зэргийг агуулсан системийн төрөл бүрийн лог файлын датаг агуулна. Алдааны репортыг зөвхөн итгэлтэй апп болон хүмүүст хуваалцана уу."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Энэ мессежийг дараагийн удаа харуулах"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Гэмтлийн тухай тайлан"</string>
diff --git a/packages/Shell/res/values-mr-rIN/strings.xml b/packages/Shell/res/values-mr-rIN/strings.xml
index 19a8706..8eb5686 100644
--- a/packages/Shell/res/values-mr-rIN/strings.xml
+++ b/packages/Shell/res/values-mr-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"शेल"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"दोष अहवाल <xliff:g id="ID">#%d</xliff:g> तयार केला जात आहे"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"दोष अहवाल <xliff:g id="ID">#%d</xliff:g> कॅप्चर केला"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"दोष अहवाल <xliff:g id="ID">#%d</xliff:g> कॅप्चर केला परंतु स्क्रीनशॉट प्रलंबित आहे"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"दोष अहवालामध्‍ये तपशील जोडत आहे"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"कृपया प्रतीक्षा करा..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"आपला दोष अहवाल सामायिक करण्यासाठी डावीकडे स्वाइप करा"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"आपला दोष अहवाल सामायिक करण्यासाठी टॅप करा"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"स्क्रीनशॉट शिवाय आपला दोष अहवाल सामायिक करण्यासाठी टॅप करा किंवा समाप्त करण्यासाठी स्क्रीनशॉटची प्रतीक्षा करा"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"स्क्रीनशॉट शिवाय आपला दोष अहवाल सामायिक करण्यासाठी टॅप करा किंवा समाप्त करण्यासाठी स्क्रीनशॉटची प्रतीक्षा करा"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"दोष अहवालांमध्‍ये वैयक्तिक आणि खाजगी माहितीसह, सिस्‍टमच्‍या अनेक लॉग फायलींमधील डेटा असतो. केवळ आपला विश्वास असलेल्‍या अ‍ॅप्‍स आणि लोकांसह दोष अहवाल सामायिक करा."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"पुढील वेळी हा संदेश दर्शवा"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"दोष अहवाल"</string>
diff --git a/packages/Shell/res/values-ms-rMY/strings.xml b/packages/Shell/res/values-ms-rMY/strings.xml
index c9f5375..46bc1a9 100644
--- a/packages/Shell/res/values-ms-rMY/strings.xml
+++ b/packages/Shell/res/values-ms-rMY/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Laporan pepijat <xliff:g id="ID">#%d</xliff:g> sedang dijana"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Laporan pepijat <xliff:g id="ID">#%d</xliff:g> telah ditangkap"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Laporan pepijat <xliff:g id="ID">#%d</xliff:g> ditangkap, menunggu tngkpn skrin"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Menambahkan butiran pada laporan pepijat"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Sila tunggu…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Leret ke kiri untuk berkongsi laporan pepijat anda"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Ketik untuk berkongsi laporan pepijat anda"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Ketik untuk berkongsi laporan pepijat anda tanpa tangkapan skrin atau tunggu tangkapan skrin selesai"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Ketik untuk berkongsi laporan pepijat anda tanpa tangkapan skrin atau tunggu tangkapan skrin selesai"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Laporan pepijat mengandungi data dari pelbagai fail log sistem, termasuk maklumat peribadi dan sulit. Kongsikan laporan pepijat hanya dengan apl dan orang yang anda percayai."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Tunjukkan mesej ini pada masa akan datang"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Laporan pepijat"</string>
diff --git a/packages/Shell/res/values-my-rMM/strings.xml b/packages/Shell/res/values-my-rMM/strings.xml
index 4250eda..6f02e70 100644
--- a/packages/Shell/res/values-my-rMM/strings.xml
+++ b/packages/Shell/res/values-my-rMM/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"အခွံ"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ချွတ်ယွင်းမှုအစီရင်ခံချက် <xliff:g id="ID">#%d</xliff:g> ကိုထုတ်နေပါသည်"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ချွတ်ယွင်းမှုအစီရင်ခံချက် <xliff:g id="ID">#%d</xliff:g> ကိုရယူထားပြီးပါပြီ"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ချွတ်ယွင်းချက် အစီရင်ခံစာ <xliff:g id="ID">#%d</xliff:g> ဖမ်းယူထားသည် သို့သော် ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း စောင့်ဆိုင်းနေသည်"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ချွတ်ယွင်းချက်အစီရင်ခံချက်သို့ အသေးစိတ်များပေါင်းထည့်ရန်"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"ခေတ္တစောင့်ပါ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"သင်၏ ဘာဂ် အစီရင်ခံစာကို မျှပေးရန် ဘယ်ဘက်သို့ ပွတ်ဆွဲရန်"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"သင့်ချွတ်ယွင်းမှုအစီရင်ခံချက်ကို မျှဝေရန် တို့ပါ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ချွတ်ယွင်းချက်အစီရင်ခံစာကို ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းမပါဘဲ မျှဝေရန် တို့ပါ သို့မဟုတ် ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း ပြီးဆုံးသည်အထိ စောင့်ပါ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ချွတ်ယွင်းချက်အစီရင်ခံစာကို ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းမပါဘဲ မျှဝေရန် တို့ပါ သို့မဟုတ် ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း ပြီးဆုံးသည်အထိ စောင့်ပါ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"အမှားအယွင်း မှတ်တမ်းမှာ ပါရှိသော အချက်အလက်များမှာ ကိုယ်ရေးကိုယ်တာ နဲ့ လုံခြုံရေး အချက်အလက်များပါဝင်သော စနစ်မှ ပြုလုပ်မှု မှတ်တမ်းများ ဖြစ်ပါသည်၊ အမှားအယွင်း မှတ်တမ်းများကို ယုံကြည်ရသော အပလီကေးရှင်းများနဲ့ လူများကိုသာ ပေးဝေပြသမှု လုပ်ပါရန်။"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ဤစာတန်းကို နောက်တစ်ခါတွင် ပြရန်"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ချို့ယွင်းမှု အစီရင်ခံစာများ"</string>
diff --git a/packages/Shell/res/values-nb/strings.xml b/packages/Shell/res/values-nb/strings.xml
index aa86ae4..0605e0e 100644
--- a/packages/Shell/res/values-nb/strings.xml
+++ b/packages/Shell/res/values-nb/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Kommandoliste"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Feilrapporten <xliff:g id="ID">#%d</xliff:g> blir generert"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Feilrapporten <xliff:g id="ID">#%d</xliff:g> er fullført"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Feilrapporten <xliff:g id="ID">#%d</xliff:g> er hentet. Venter på skjermdumpen"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Legger til detaljer i feilrapporten"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Vent litt"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Sveip til venstre for å dele feilrapporten din"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Trykk for å dele feilrapporten"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Trykk for å dele feilrapporten uten noen skjermdump, eller vent til skjermdumpen er klar"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Trykk for å dele feilrapporten uten noen skjermdump, eller vent til skjermdumpen er klar"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Feilrapporter inkluderer data fra systemets forskjellige loggfiler. Dette omfatter personlig og privat informasjon. Du bør bare dele feilrapporter med apper og folk du stoler på."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Vis denne meldingen neste gang"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Feilrapporter"</string>
diff --git a/packages/Shell/res/values-ne-rNP/strings.xml b/packages/Shell/res/values-ne-rNP/strings.xml
index 43c2a5c..906d824 100644
--- a/packages/Shell/res/values-ne-rNP/strings.xml
+++ b/packages/Shell/res/values-ne-rNP/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"सेल"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g>लाई निकालिदैछ"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g>लाई कैद गरियो"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g> लाई क्याप्चर गरियो तर स्क्रिनसट बाँकी रहेको छ"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"बग रिपोर्टमा विवरणहरू थप्दै"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"कृपया प्रतीक्षा गर्नुहोला..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"तपाईँको बग रिपोर्ट साझेदारी गर्न बायाँ स्वाइप गर्नुहोस्"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"तपाईंको बग रिपोर्टलाई साझेदारी गर्न ट्याप गर्नुहोस्"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुन प्रतीक्षा गर्नुहोस्"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुन प्रतीक्षा गर्नुहोस्"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"बग रिपोर्टहरूमा प्रणालीका विभिन्न लग फाइलहरूबाट व्यक्तिगत तथा नीजि सूचनासहितको डेटा रहन्छ।  बग रिपोर्टहरू अनुप्रयोगहरू र तपाईँले विश्वास गरेका व्यक्तिहरूसँग मात्र साझेदारी गर्नुहोस्।"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"यो सन्देश अर्को पटक देखाउनुहोस्"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"बग रिपोर्टहरू"</string>
diff --git a/packages/Shell/res/values-nl/strings.xml b/packages/Shell/res/values-nl/strings.xml
index 01fd577..3022691 100644
--- a/packages/Shell/res/values-nl/strings.xml
+++ b/packages/Shell/res/values-nl/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Bugrapport <xliff:g id="ID">#%d</xliff:g> wordt gegenereerd"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Bugrapport <xliff:g id="ID">#%d</xliff:g> is vastgelegd"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Bugrapport <xliff:g id="ID">#%d</xliff:g> vastgelegd, screenshot in behandeling"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Details toevoegen aan het bugrapport"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Even geduld…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Veeg naar links om je bugmelding te delen"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tik om je bugrapport te delen"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tik om je bugrapport te delen zonder screenshot of wacht tot het screenshot is voltooid"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tik om je bugrapport te delen zonder screenshot of wacht tot het screenshot is voltooid"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Foutenrapporten bevatten gegevens uit de verschillende logbestanden van het systeem, waaronder persoonlijke en privégegevens. Deel foutenrapporten alleen met apps en mensen die u vertrouwt."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Dit bericht de volgende keer weergeven"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Foutenrapporten"</string>
diff --git a/packages/Shell/res/values-pa-rIN/strings.xml b/packages/Shell/res/values-pa-rIN/strings.xml
index 3494199..d44daf7 100644
--- a/packages/Shell/res/values-pa-rIN/strings.xml
+++ b/packages/Shell/res/values-pa-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"ਸ਼ੈਲ"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ਬੱਗ ਰਿਪੋਰਟ <xliff:g id="ID">#%d</xliff:g> ਸਿਰਜੀ ਜਾ ਰਹੀ ਹੈ"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ਬੱਗ ਰਿਪੋਰਟ <xliff:g id="ID">#%d</xliff:g> ਕੈਪਚਰ ਕੀਤੀ ਗਈ"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ਬੱਗ ਰਿਪੋਰਟ <xliff:g id="ID">#%d</xliff:g> ਕੈਪਚਰ ਕੀਤੀ ਗਈ ਪਰ ਸਕ੍ਰੀਨਸ਼ਾਟ ਅਧੂਰਾ ਹੈ"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ਬੱਗ ਰਿਪੋਰਟ ਵਿੱਚ ਵੇਰਵਿਆਂ ਨੂੰ ਸ਼ਾਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"ਕਿਰਪਾ ਕਰਕੇ ਉਡੀਕ ਕਰੋ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"ਤੁਹਾਡੀ ਬਗ ਰਿਪੋਰਟ ਸ਼ੇਅਰ ਕਰਨ ਲਈ ਖੱਬੇ ਪਾਸੇ ਸਵਾਈਪ ਕਰੋ"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਸਾਂਝੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਬਿਨਾਂ ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਨੂੰ ਸਾਂਝੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ ਜਾਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਪੂਰੇ ਹੋਣ ਦੀ ਉਡੀਕ ਕਰੋ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਬਿਨਾਂ ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਨੂੰ ਸਾਂਝੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ ਜਾਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਪੂਰੇ ਹੋਣ ਦੀ ਉਡੀਕ ਕਰੋ"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"ਬਗ ਰਿਪੋਰਟਾਂ ਵਿੱਚ ਸਿਸਟਮ ਦੀਆਂ ਭਿੰਨ ਲੌਗ ਫਾਈਲਾਂ ਦਾ ਡਾਟਾ ਹੁੰਦਾ ਹੈ, ਨਿੱਜੀ ਅਤੇ ਪ੍ਰਾਈਵੇਟ ਜਾਣਕਾਰੀ ਸਮੇਤ। ਕੇਵਲ ਉਹਨਾਂ ਐਪਸ ਅਤੇ ਲੋਕਾਂ ਨਾਲ ਬਗ ਰਿਪੋਰਟਾਂ ਸ਼ੇਅਰ ਕਰੋ, ਜਿਹਨਾਂ ਤੇ ਤੁਸੀਂ ਭਰੋਸਾ ਕਰਦੇ ਹੋ।"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ਅਗਲੀ ਵਾਰ ਇਹ ਸੁਨੇਹਾ ਦਿਖਾਓ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ਬਗ ਰਿਪੋਰਟਾਂ"</string>
diff --git a/packages/Shell/res/values-pl/strings.xml b/packages/Shell/res/values-pl/strings.xml
index 91934c9..b4977a4 100644
--- a/packages/Shell/res/values-pl/strings.xml
+++ b/packages/Shell/res/values-pl/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Powłoka"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Generuję raport o błędzie <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Raport o błędzie <xliff:g id="ID">#%d</xliff:g> został zapisany"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Raport <xliff:g id="ID">#%d</xliff:g> zapisany. Zrzut nie jest jeszcze gotowy"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodaję szczegóły do raportu o błędzie"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Czekaj..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Przesuń palcem w lewo, by udostępnić swoje zgłoszenie błędu"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Kliknij, by udostępnić raport o błędzie"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Kliknij, by udostępnić raport o błędzie bez zrzutu ekranu, lub poczekaj, aż zostanie on wygenerowany"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Kliknij, by udostępnić raport o błędzie bez zrzutu ekranu, lub poczekaj, aż zostanie on wygenerowany"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Raporty o błędach zawierają dane z różnych plików dzienników systemu, w tym dane osobowe i prywatne. Udostępniaj je tylko aplikacjom i osobom, którym ufasz."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Pokaż ten komunikat następnym razem"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Raporty o błędach"</string>
diff --git a/packages/Shell/res/values-pt-rBR/strings.xml b/packages/Shell/res/values-pt-rBR/strings.xml
index 41f4e24..2306c39 100644
--- a/packages/Shell/res/values-pt-rBR/strings.xml
+++ b/packages/Shell/res/values-pt-rBR/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"O relatório do bug <xliff:g id="ID">#%d</xliff:g> está sendo gerado"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Relatório do bug <xliff:g id="ID">#%d</xliff:g> capturado"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Relatório do bug <xliff:g id="ID">#%d</xliff:g> capturado, captura pendente"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Adicionando detalhes ao relatório do bug"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Aguarde…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Deslize para a esquerda para compartilhar seu relatório de bugs"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toque para compartilhar seu relatório do bug"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de bugs contêm dados de diversos arquivos de registro do sistema, inclusive informações pessoais e particulares. Compartilhe relatórios de bugs somente com apps e pessoas nos quais você confia."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensagem da próxima vez"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Relatórios de bugs"</string>
diff --git a/packages/Shell/res/values-pt-rPT/strings.xml b/packages/Shell/res/values-pt-rPT/strings.xml
index 416db80..7daed8b 100644
--- a/packages/Shell/res/values-pt-rPT/strings.xml
+++ b/packages/Shell/res/values-pt-rPT/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"O relatório de erro <xliff:g id="ID">#%d</xliff:g> está a ser criado"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Relatório de erro <xliff:g id="ID">#%d</xliff:g> criado"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Rel. de erro <xliff:g id="ID">#%d</xliff:g> capturado, captura de ecrã pendente"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"A adicionar detalhes ao relatório de erro"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Aguarde..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Deslizar rapidamente para a esquerda para partilhar o seu relatório de erros"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toque para partilhar o relatório de erro"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toque para partilhar o relatório de erro sem uma captura de ecrã ou aguarde a conclusão da mesma"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toque para partilhar o relatório de erro sem uma captura de ecrã ou aguarde a conclusão da mesma"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de erros incluem dados de vários ficheiros de registo do sistema, nomeadamente informações pessoais e privadas. Partilhe relatórios de erros apenas com aplicações e pessoas fidedignas."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensagem da próxima vez"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Relatórios de erros"</string>
diff --git a/packages/Shell/res/values-pt/strings.xml b/packages/Shell/res/values-pt/strings.xml
index 41f4e24..2306c39 100644
--- a/packages/Shell/res/values-pt/strings.xml
+++ b/packages/Shell/res/values-pt/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"O relatório do bug <xliff:g id="ID">#%d</xliff:g> está sendo gerado"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Relatório do bug <xliff:g id="ID">#%d</xliff:g> capturado"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Relatório do bug <xliff:g id="ID">#%d</xliff:g> capturado, captura pendente"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Adicionando detalhes ao relatório do bug"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Aguarde…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Deslize para a esquerda para compartilhar seu relatório de bugs"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toque para compartilhar seu relatório do bug"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de bugs contêm dados de diversos arquivos de registro do sistema, inclusive informações pessoais e particulares. Compartilhe relatórios de bugs somente com apps e pessoas nos quais você confia."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensagem da próxima vez"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Relatórios de bugs"</string>
diff --git a/packages/Shell/res/values-ro/strings.xml b/packages/Shell/res/values-ro/strings.xml
index 4112e60..9529ade 100644
--- a/packages/Shell/res/values-ro/strings.xml
+++ b/packages/Shell/res/values-ro/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Raportul de eroare <xliff:g id="ID">#%d</xliff:g> se generează"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Raportul de eroare <xliff:g id="ID">#%d</xliff:g> a fost creat"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Raport eroare <xliff:g id="ID">#%d</xliff:g> creat, captură ecran în așteptare"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Se adaugă detaliile la raportul de eroare"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Așteptați…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Glisați la stânga pentru a trimite raportul de erori"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Atingeți pentru a trimite raportul de eroare"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Atingeți ca să trimiteți raportul de eroare fără captură de ecran sau așteptați finalizarea acesteia"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Atingeți ca să trimiteți raportul de eroare fără captură de ecran sau așteptați finalizarea acesteia"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Rapoartele despre erori conțin date din diferite fișiere de jurnal ale sistemului, inclusiv informații private și personale. Permiteți accesul la rapoartele despre erori numai aplicațiilor și persoanelor în care aveți încredere."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afișați acest mesaj data viitoare"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapoarte de erori"</string>
diff --git a/packages/Shell/res/values-ru/strings.xml b/packages/Shell/res/values-ru/strings.xml
index ffd2e66..4aafbba 100644
--- a/packages/Shell/res/values-ru/strings.xml
+++ b/packages/Shell/res/values-ru/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Оболочка"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Создание отчета об ошибке <xliff:g id="ID">#%d</xliff:g>…"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Отчет об ошибке <xliff:g id="ID">#%d</xliff:g> сохранен"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Отчет об ошибке (<xliff:g id="ID">#%d</xliff:g>) готов, ожидается скриншот"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Добавление данных в отчет об ошибке"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Подождите…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Проведите влево, чтобы отправить отчет"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Нажмите, чтобы отправить отчет об ошибке."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Нажмите, чтобы отправить отчет об ошибке сразу, или подождите, пока будет сохранен скриншот."</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Нажмите, чтобы отправить отчет об ошибке сразу, или подождите, пока будет сохранен скриншот."</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Отчеты об ошибках содержат данные различных системных журналов и могут включать личную информацию. Рекомендуем открывать к ним доступ только лицам и приложениям, заслуживающим доверие."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Показать это сообщение в следующий раз"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Отчеты об ошибках"</string>
diff --git a/packages/Shell/res/values-si-rLK/strings.xml b/packages/Shell/res/values-si-rLK/strings.xml
index 807ebb1..1ea7586 100644
--- a/packages/Shell/res/values-si-rLK/strings.xml
+++ b/packages/Shell/res/values-si-rLK/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"ෂෙල්"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"දෝෂ වාර්තා <xliff:g id="ID">#%d</xliff:g> ජනනය කරමින් පවතී"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"දෝෂ වාර්තා <xliff:g id="ID">#%d</xliff:g> ග්‍රහණය කර ගන්නා ලදී"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"දෝෂ වාර්තාව <xliff:g id="ID">#%d</xliff:g> ග්‍රහණය කළ නමුත් තිර රුව පොරොත්තුව ඇත"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"දෝෂ වාර්තාව වෙත විස්තර එක් කිරීම"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"කරුණාකර රැඳී සිටින්න..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"ඔබගේ දෝෂ වාර්තාව බෙදාගැනීමට වමට ස්වයිප් කරන්න"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"ඔබගේ දෝෂ වාර්තාව බෙදා ගැනීමට තට්ටු කරන්න"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"තිර රුවක් රහිතව ඔබගේ දෝෂ වාර්තාව බෙදා ගැනීමට තට්ටු කරන්න නැතහොත් තිර රුව ගැනීම අවසන් වන තෙක් රැඳෙන්න"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"තිර රුවක් රහිතව ඔබගේ දෝෂ වාර්තාව බෙදා ගැනීමට තට්ටු කරන්න නැතහොත් තිර රුව ගැනීම අවසන් වන තෙක් රැඳෙන්න"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"පුද්ගලික සහ පෞද්ගලික තොරතුරු ඇතුළත්ව පද්ධතියේ විවිධ ලොග් ගොනු වල දත්ත දෝෂ වාර්තාවේ අඩංගු වේ. ඔබට විශ්වාසවන්ත යෙදුම් සහ පුද්ගලයින් සමඟ පමණක් දෝෂ වාර්තා බෙදා ගන්න."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ඊළඟ වෙලාවේ මෙම පණිවිඩය පෙන්වන්න"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"දෝෂ වාර්තා"</string>
diff --git a/packages/Shell/res/values-sk/strings.xml b/packages/Shell/res/values-sk/strings.xml
index a62a6eb..7a78c43 100644
--- a/packages/Shell/res/values-sk/strings.xml
+++ b/packages/Shell/res/values-sk/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Prostredie"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Generuje sa hlásenie chyby <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Hlásenie chyby <xliff:g id="ID">#%d</xliff:g> bolo zaznamenané"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Chyba <xliff:g id="ID">#%d</xliff:g> bola zaznamenaná, čaká sa na snímku obrazovky"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Pridanie podrobností o hlásení chyby"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Čakajte prosím…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Ak chcete hlásenie o chybe zdieľať, prejdite prstom doľava."</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Hlásenie chyby môžete zdieľať klepnutím"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Klepnutím zdieľajte hlásenie chyby bez snímky obrazovky alebo počkajte na dokončenie snímky obrazovky"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Klepnutím zdieľajte hlásenie chyby bez snímky obrazovky alebo počkajte na dokončenie snímky obrazovky"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Správy o chybách obsahujú údaje z rôznych súborov denníkov systému vrátane osobných a súkromných informácií. Zdieľajte ich iba s dôveryhodnými aplikáciami a ľuďmi."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Zobraziť túto správu nabudúce"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Hlásenia chýb"</string>
diff --git a/packages/Shell/res/values-sl/strings.xml b/packages/Shell/res/values-sl/strings.xml
index 6d1be5a..fdf3446 100644
--- a/packages/Shell/res/values-sl/strings.xml
+++ b/packages/Shell/res/values-sl/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Lupina"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Poročilo o napaki <xliff:g id="ID">#%d</xliff:g> je v izdelavi"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Poročilo o napaki <xliff:g id="ID">#%d</xliff:g> zajeto"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Poroč. o napakah <xliff:g id="ID">#%d</xliff:g> zajeto, posnetek zaslona nastaja"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodajanje podrobnosti v poročilo o napakah"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Počakajte ..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Povlecite v levo, če želite poslati sporočilo o napaki"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Dotaknite se, če želite poročilo o napaki dati v skupno rabo"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Dotaknite se za pošiljanje poročila o napakah brez posnetka zaslona ali počakajte, da se ta dokonča"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Dotaknite se za pošiljanje poročila o napakah brez posnetka zaslona ali počakajte, da se ta dokonča"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Poročila o napakah vsebujejo podatke iz različnih dnevniških datotek sistema, vključno z osebnimi in zasebnimi podatki. Poročila o napakah delite samo z aplikacijami in ljudmi, ki jim zaupate."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Pokaži to sporočilo naslednjič"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Poročila o napakah"</string>
diff --git a/packages/Shell/res/values-sq-rAL/strings.xml b/packages/Shell/res/values-sq-rAL/strings.xml
index ce990e9..f43ce9f 100644
--- a/packages/Shell/res/values-sq-rAL/strings.xml
+++ b/packages/Shell/res/values-sq-rAL/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Guaska"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Raporti i defekteve në kod <xliff:g id="ID">#%d</xliff:g> po krijohet"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Raporti i defekteve në kod <xliff:g id="ID">#%d</xliff:g> u regjistrua"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Raporti i defekteve në kod <xliff:g id="ID">#%d</xliff:g> u regjistrua, por pamja e çastit është në pritje"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Po shtohen detajet te raporti i defekteve në kod"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Qëndro në pritje..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Rrëshqit majtas për të ndarë raportin e defektit në kod"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Trokit për të ndarë raportin e defekteve në kod"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Trokit për të ndarë raportin e defekteve në kod pa një pamje çasti ose prit që pamja e çastit të përfundojë"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Trokit për të ndarë raportin e defekteve në kod pa një pamje çasti ose prit që pamja e çastit të përfundojë"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Raportet e gabimeve përmbajnë të dhëna nga skedarë të ndryshëm ditarësh sistemi, përfshi informacione personale dhe private. Shpërndaji publikisht raportet e gabimeve vetëm me aplikacionet dhe personat që iu beson."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Tregoje këtë mesazh herën tjetër"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Raportet e gabimeve"</string>
diff --git a/packages/Shell/res/values-sr/strings.xml b/packages/Shell/res/values-sr/strings.xml
index 0157a25..3bea4f3 100644
--- a/packages/Shell/res/values-sr/strings.xml
+++ b/packages/Shell/res/values-sr/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Извештај о грешци <xliff:g id="ID">#%d</xliff:g> се генерише"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Извештај о грешци <xliff:g id="ID">#%d</xliff:g> је снимљен"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Извештај о грешци <xliff:g id="ID">#%d</xliff:g> снимљен; снимак екрана се чека"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Додају се детаљи у извештај о грешци"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Сачекајте..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Превуците улево да бисте делили извештај о грешкама"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Додирните да бисте делили извештај о грешци"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Додирните за дељење извештаја о грешци без снимка екрана или сачекајте да се направи снимак екрана"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Додирните за дељење извештаја о грешци без снимка екрана или сачекајте да се направи снимак екрана"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Извештаји о грешкама садрже податке из различитих системских датотека евиденције, укључујући личне и приватне податке. Делите извештаје о грешкама само са апликацијама и људима у које имате поверења."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Прикажи ову поруку следећи пут"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Извештаји о грешкама"</string>
diff --git a/packages/Shell/res/values-sv/strings.xml b/packages/Shell/res/values-sv/strings.xml
index 88af0db..a8cb64d 100644
--- a/packages/Shell/res/values-sv/strings.xml
+++ b/packages/Shell/res/values-sv/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Skal"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Felrapporten <xliff:g id="ID">#%d</xliff:g> genereras"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Felrapporten <xliff:g id="ID">#%d</xliff:g> har skapats"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Felrapporten <xliff:g id="ID">#%d</xliff:g> har skapats, väntar på skärmdumpen"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Lägger till information i felrapporten"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Vänta …"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Svep åt vänster om du vill dela felrapporten"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tryck om du vill dela felrapporten"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tryck om du vill dela felrapporten utan en skärmdump eller vänta tills skärmdumpen är klar"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tryck om du vill dela felrapporten utan en skärmdump eller vänta tills skärmdumpen är klar"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Felrapporter innehåller data från systemets olika loggfiler, inklusive personliga och privata uppgifter. Dela bara felrapporter med personer du litar på."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Visa det här meddelandet nästa gång"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Felrapporter"</string>
diff --git a/packages/Shell/res/values-sw/strings.xml b/packages/Shell/res/values-sw/strings.xml
index 01df55e..945bb60 100644
--- a/packages/Shell/res/values-sw/strings.xml
+++ b/packages/Shell/res/values-sw/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Ganda"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Ripoti ya hitilafu ya <xliff:g id="ID">#%d</xliff:g> inatayarishwa"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Ripoti ya hitilafu ya <xliff:g id="ID">#%d</xliff:g> imerekodiwa"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Ripoti ya hitilafu ya <xliff:g id="ID">#%d</xliff:g> imerekodiwa lakini picha ya skrini bado haijakamilishwa"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Inaongeza maelezo kwenye ripoti ya hitilafu"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Tafadhali subiri…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Telezesha kidole kushoto ili ushiriki ripoti yako ya hitilafu"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Gonga ili ushiriki ripoti yako ya hitilafu"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Gonga ili ushiriki ripoti yako ya hitilafu bila picha ya skrini au usubiri picha ya skrini itayarishwe"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Gonga ili ushiriki ripoti yako ya hitilafu bila picha ya skrini au usubiri picha ya skrini itayarishwe"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Ripoti ya hitilafu ina data kutoka kwenye faili za kumbukumbu mbalimbali za mfumo, pamoja na maelezo ya kibinafsi na faragha. Shiriki ripoti ya hitilafu na programu na watu unaowaamini pekee."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Onyesha ujumbe huu wakati mwingine"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Ripoti za hitilafu"</string>
diff --git a/packages/Shell/res/values-ta-rIN/strings.xml b/packages/Shell/res/values-ta-rIN/strings.xml
index c14da56..a501764 100644
--- a/packages/Shell/res/values-ta-rIN/strings.xml
+++ b/packages/Shell/res/values-ta-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"ஷெல்"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"பிழை அறிக்கை <xliff:g id="ID">#%d</xliff:g> உருவாக்கப்படுகிறது"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"பிழை அறிக்கை <xliff:g id="ID">#%d</xliff:g> எடுக்கப்பட்டது"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"பிழை அறிக்கை <xliff:g id="ID">#%d</xliff:g> எடுக்கப்பட்டது ஆனால் ஸ்கிரீன்ஷாட் நிலுவையிலுள்ளது"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"பிழை அறிக்கையில் விவரங்களைச் சேர்க்கிறது"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"காத்திருக்கவும்…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"பிழை அறிக்கையைப் பகிர இடது புறமாகத் தேய்க்கவும்"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"பிழை அறிக்கையைப் பகிர, தட்டவும்"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ஸ்கிரீன்ஷாட் இல்லாமல் பிழை அறிக்கையைப் பகிர, தட்டவும் அல்லது ஸ்கிரீன்ஷாட் முடியும்வரை காத்திருக்கவும்"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ஸ்கிரீன்ஷாட் இல்லாமல் பிழை அறிக்கையைப் பகிர, தட்டவும் அல்லது ஸ்கிரீன்ஷாட் முடியும்வரை காத்திருக்கவும்"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"பிழை அறிக்கைகளில், சொந்த வாழ்க்கை மற்றும் தனிப்பட்ட தகவல் உள்பட கணினியின் பல்வேறு பதிவுகளில் உள்ள தரவு இருக்கும். நீங்கள் நம்பும் பயன்பாடுகள் மற்றும் நபர்களுடன் மட்டும் பிழை அறிக்கைகளைப் பகிரவும்."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"இந்தச் செய்தியை அடுத்த முறைக் காட்டு"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"பிழை அறிக்கைகள்"</string>
diff --git a/packages/Shell/res/values-te-rIN/strings.xml b/packages/Shell/res/values-te-rIN/strings.xml
index 3ed1f95..f406869 100644
--- a/packages/Shell/res/values-te-rIN/strings.xml
+++ b/packages/Shell/res/values-te-rIN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"షెల్"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"బగ్ నివేదిక <xliff:g id="ID">#%d</xliff:g> ఉత్పాదించబడుతోంది"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"బగ్ నివేదిక <xliff:g id="ID">#%d</xliff:g> సంగ్రహించబడింది"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"బగ్ నివే. <xliff:g id="ID">#%d</xliff:g> క్యాప్చ., కానీ స్క్రీన్‌షాట్ పెం. ఉంది"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"బగ్ నివేదికకు వివరాలను జోడిస్తోంది"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"దయచేసి వేచి ఉండండి..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"మీ బగ్ నివేదికను భాగస్వామ్యం చేయడానికి ఎడమవైపుకు స్వైప్ చేయండి"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"మీ బగ్ నివేదికను భాగస్వామ్యం చేయడానికి నొక్కండి"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"స్క్రీన్‌షాట్ లేకుండా మీ బగ్ నివే. భాగ. చేయడానికి నొక్కండి లేదా స్క్రీన్‌షాట్ ముగిసేదాకా వేచి ఉండండి"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"స్క్రీన్‌షాట్ లేకుండా మీ బగ్ నివే. భాగ. చేయడానికి నొక్కండి లేదా స్క్రీన్‌షాట్ ముగిసేదాకా వేచి ఉండండి"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"బగ్ నివేదికలు వ్యక్తిగతమైన మరియు రహస్యమైన సమాచారంతో సహా సిస్టమ్ యొక్క విభిన్న లాగ్ ఫైల్‌ల్లోని డేటాను కలిగి ఉంటాయి. కనుక బగ్ నివేదికలను మీరు విశ్వసించే అనువర్తనాలు మరియు వ్యక్తులతో మాత్రమే భాగస్వామ్యం చేయండి."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"తదుపరిసారి ఈ సందేశాన్ని చూపు"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"బగ్ నివేదికలు"</string>
diff --git a/packages/Shell/res/values-th/strings.xml b/packages/Shell/res/values-th/strings.xml
index f28bac6..db7f823 100644
--- a/packages/Shell/res/values-th/strings.xml
+++ b/packages/Shell/res/values-th/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"กำลังสร้างรายงานข้อบกพร่อง <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"บันทึกรายงานข้อบกพร่อง <xliff:g id="ID">#%d</xliff:g> แล้ว"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"จับภาพรายงานข้อบกพร่อง <xliff:g id="ID">#%d</xliff:g> แล้วแต่ภาพหน้าจอยังไม่เสร็จ"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"กำลังเพิ่มรายละเอียดในรายงานข้อบกพร่อง"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"โปรดรอสักครู่…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"กวาดไปทางซ้ายเพื่อแชร์รายงานข้อบกพร่อง"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"แตะเพื่อแชร์รายงานข้อบกพร่องของคุณ"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"แตะเพื่อแชร์รายงานข้อบกพร่องของคุณโดยไม่มีภาพหน้าจอ หรือรอให้ภาพหน้าจอเสร็จสมบูรณ์"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"แตะเพื่อแชร์รายงานข้อบกพร่องของคุณโดยไม่มีภาพหน้าจอ หรือรอให้ภาพหน้าจอเสร็จสมบูรณ์"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"รายงานข้อบกพร่องมีข้อมูลจากไฟล์บันทึกต่างๆ ของระบบ รวมถึงข้อมูลส่วนตัว แชร์รายงานข้อบกพร่องกับแอปและบุคคลที่คุณไว้ใจเท่านั้น"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"แสดงข้อความนี้ในครั้งต่อไป"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"รายงานข้อบกพร่อง"</string>
diff --git a/packages/Shell/res/values-tl/strings.xml b/packages/Shell/res/values-tl/strings.xml
index d270401..f99a1b8 100644
--- a/packages/Shell/res/values-tl/strings.xml
+++ b/packages/Shell/res/values-tl/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Binubuo na ang ulat ng bug na <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Na-capture ang ulat ng bug na <xliff:g id="ID">#%d</xliff:g>"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Nakunan ang ulat ng bug <xliff:g id="ID">#%d</xliff:g>, nakabinbin ang screenshot"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Pagdaragdag ng mga detalye sa ulat ng bug"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Mangyaring maghintay..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Mag-swipe pakaliwa upang ibahagi ang iyong ulat ng bug"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Mag-tap upang ibahagi ang iyong ulat ng bug"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Mag-tap para ibahagi ang iyong ulat ng bug nang walang screenshot o hintaying matapos ang screenshot"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Mag-tap para ibahagi ang iyong ulat ng bug nang walang screenshot o hintaying matapos ang screenshot"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Naglalaman ang mga ulat ng bug ng data mula sa iba\'t ibang file ng log ng system, kabilang ang personal at pribadong impormasyon. Magbahagi lang ng mga ulat ng bug sa apps at mga tao na pinagkakatiwalaan mo."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Ipakita ang mensaheng ito sa susunod"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Mga ulat sa bug"</string>
diff --git a/packages/Shell/res/values-tr/strings.xml b/packages/Shell/res/values-tr/strings.xml
index 6da3490..be448af 100644
--- a/packages/Shell/res/values-tr/strings.xml
+++ b/packages/Shell/res/values-tr/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Kabuk"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Hata raporu (<xliff:g id="ID">#%d</xliff:g>) oluşturuluyor"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Hata raporu (<xliff:g id="ID">#%d</xliff:g>) yakalandı"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"<xliff:g id="ID">#%d</xliff:g> hata raporu yakalandı, ekran görüntüsü bekleniyor"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Hata raporuna ayrıntılar ekleniyor"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Lütfen bekleyin…"</string>
     <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="8353769438382138847">"Hata raporunuzu paylaşmak için hafifçe dokunun"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Hata raporunu ekran görüntüsüz paylaşmak için dokunun veya bitirmek için ekran görüntüsünü bekleyin"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Hata raporunu ekran görüntüsüz paylaşmak için dokunun veya bitirmek için ekran görüntüsünü bekleyin"</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 iletiyi göster"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Hata raporları"</string>
diff --git a/packages/Shell/res/values-uk/strings.xml b/packages/Shell/res/values-uk/strings.xml
index 00a7793..c35c61c 100644
--- a/packages/Shell/res/values-uk/strings.xml
+++ b/packages/Shell/res/values-uk/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Оболонка"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Генерується повідомлення про помилку <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Повідомлення про помилку <xliff:g id="ID">#%d</xliff:g> створено"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Повідомлення <xliff:g id="ID">#%d</xliff:g> створено. Очікується знімок екрана"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Додаються деталі до повідомлення про помилку"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Зачекайте…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Проведіть пальцем ліворуч, щоб надіслати звіт про помилки"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Торкніться, щоб надіслати повідомлення про помилку"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Торкніться, щоб надіслати повідомлення про помилку без знімка екрана або зачекайте на знімок"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Торкніться, щоб надіслати повідомлення про помилку без знімка екрана або зачекайте на знімок"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Звіти про помилки містять дані з різних файлів журналу системи, зокрема особисті та конфіденційні. Надсилайте звіт про помилки лише тим, кому довіряєте."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Показати це повідомлення наступного разу"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Звіти про помилки"</string>
diff --git a/packages/Shell/res/values-ur-rPK/strings.xml b/packages/Shell/res/values-ur-rPK/strings.xml
index abf6940..ef6801f 100644
--- a/packages/Shell/res/values-ur-rPK/strings.xml
+++ b/packages/Shell/res/values-ur-rPK/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"شیل"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"بگ رپورٹ <xliff:g id="ID">#%d</xliff:g> تخلیق ہو رہی ہے"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"بگ رپورٹ <xliff:g id="ID">#%d</xliff:g> کیپچر ہو گئی"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"بگ رپورٹ <xliff:g id="ID">#%d</xliff:g> کیپچر ہو گیا مگر اسکرین شاٹ زیر التواء"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"بگ رپورٹ میں تفصیلات شامل کی جا رہی ہیں"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"براہ کرم انتظار کریں…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"اپنی بگ رپورٹ کا اشتراک کرنے کیلئے بائیں سوائپ کریں"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"اپنی بگ رپورٹ کا اشتراک کرنے کیلئے تھپتھپائیں"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"بغیر اسکرین شاٹ کے بگ رپورٹ کا اشتراک کرنے کیلئے تھپتھپائیں یا اسکرین شاٹ کے ختم ہونے کا انتظار کریں"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"بغیر اسکرین شاٹ کے بگ رپورٹ کا اشتراک کرنے کیلئے تھپتھپائیں یا اسکرین شاٹ کے ختم ہونے کا انتظار کریں"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"بَگ رپورٹس میں سسٹم کی مختلف لاگ فائلوں سے ڈیٹا شامل ہوتا ہے، بشمول ذاتی اور نجی معلومات۔ بَگ رپورٹس کا اشتراک صرف اپنے بھروسے مند ایپس اور لوگوں کے ساتھ کریں۔"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"یہ پیغام اگلی بار دکھائیں"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"بگ رپورٹس"</string>
diff --git a/packages/Shell/res/values-uz-rUZ/strings.xml b/packages/Shell/res/values-uz-rUZ/strings.xml
index 7782b42..dd7f41b 100644
--- a/packages/Shell/res/values-uz-rUZ/strings.xml
+++ b/packages/Shell/res/values-uz-rUZ/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Terminal"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Xatoliklar hisoboti (<xliff:g id="ID">#%d</xliff:g>) tayyorlanmoqda"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Xatoliklar hisoboti (<xliff:g id="ID">#%d</xliff:g>) yozib olindi"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Xatoliklar hisoboti (<xliff:g id="ID">#%d</xliff:g>) tayyor, skrinshot kutilmoqda"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Xatoliklar hisobotiga tafsilotlar qo‘shilmoqda"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Iltimos, kuting…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Xatolik hisobotini yuborish uchun barmog‘ingiz bilan chapga suring"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Xatoliklar hisobotini ulashish uchun bosing"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Xatoliklar hisobotini darhol yuborish uchun shu yerga bosing yoki skrinshot saqlanguncha kuting"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Xatoliklar hisobotini darhol yuborish uchun shu yerga bosing yoki skrinshot saqlanguncha kuting"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Xatolik hisobotlari tizimdagi har xil jurnal fayllardagi ma’lumotlarni, shuningdek, shaxsiy hamda maxfiy ma’lumotlarni o‘z ichiga oladi. Xatolik hisobotlarini faqat ishonchli dasturlar va odamlar bilan bo‘lishing."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Ushbu xabar keyingi safar ko‘rsatilsin"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Xatoliklar hisoboti"</string>
diff --git a/packages/Shell/res/values-vi/strings.xml b/packages/Shell/res/values-vi/strings.xml
index 27a9c7f..2229991 100644
--- a/packages/Shell/res/values-vi/strings.xml
+++ b/packages/Shell/res/values-vi/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Báo cáo lỗi <xliff:g id="ID">#%d</xliff:g> đang được tạo"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Đã chụp báo cáo lỗi <xliff:g id="ID">#%d</xliff:g>"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Đã chụp báo cáo lỗi <xliff:g id="ID">#%d</xliff:g>, đang chờ ảnh chụp màn hình"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Đang thêm thông tin chi tiết vào báo cáo lỗi"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Vui lòng đợi…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Vuốt sang trái để chia sẻ báo cáo lỗi của bạn"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Nhấn để chia sẻ báo cáo lỗi của bạn"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Bấm để chia sẻ báo cáo lỗi mà không cần ảnh chụp màn hình hoặc đợi hoàn tất ảnh chụp màn hình"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Bấm để chia sẻ báo cáo lỗi mà không cần ảnh chụp màn hình hoặc đợi hoàn tất ảnh chụp màn hình"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Các báo cáo lỗi chứa dữ liệu từ nhiều tệp nhật ký khác nhau của hệ thống, bao gồm cả thông tin cá nhân và riêng tư. Chỉ chia sẻ báo cáo lỗi với các ứng dụng và những người mà bạn tin tưởng."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Hiển thị thông báo này vào lần tới"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Báo cáo lỗi"</string>
diff --git a/packages/Shell/res/values-zh-rCN/strings.xml b/packages/Shell/res/values-zh-rCN/strings.xml
index 65cfbbc..b09a7d0 100644
--- a/packages/Shell/res/values-zh-rCN/strings.xml
+++ b/packages/Shell/res/values-zh-rCN/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"正在生成错误报告 <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"已捕获错误报告 <xliff:g id="ID">#%d</xliff:g>"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"已捕获错误报告 <xliff:g id="ID">#%d</xliff:g>,但仍在等待屏幕截图完成"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"正在向错误报告添加详细信息"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"请稍候…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"向左滑动即可分享错误报告"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"点按即可分享您的错误报告"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"点按即可分享不含屏幕截图的错误报告;您也可以等待屏幕截图完成"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"点按即可分享不含屏幕截图的错误报告;您也可以等待屏幕截图完成"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"错误报告包含的数据来自于系统的各个日志文件,其中包含个人信息和隐私信息。请务必只与您信任的应用和用户分享错误报告。"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次再显示这条讯息"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"错误报告"</string>
diff --git a/packages/Shell/res/values-zh-rHK/strings.xml b/packages/Shell/res/values-zh-rHK/strings.xml
index 34a849e..384eee7 100644
--- a/packages/Shell/res/values-zh-rHK/strings.xml
+++ b/packages/Shell/res/values-zh-rHK/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"命令介面"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"正在產生錯誤報告 <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"已擷取錯誤報告 <xliff:g id="ID">#%d</xliff:g>"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"已擷取錯誤報告 <xliff:g id="ID">#%d</xliff:g>,但螢幕畫面仍未擷取完成"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"正在新增錯誤報告詳細資訊"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"請稍候…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"向左滑動即可分享錯誤報告"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"輕按即可分享錯誤報告"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"輕按以分享錯誤報告 (不包含螢幕擷圖),或等待螢幕畫面擷取完成"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"輕按以分享錯誤報告 (不包含螢幕擷圖),或等待螢幕畫面擷取完成"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"錯誤報告中有來自系統各個記錄檔案的資料,包括個人和私人資料。請只與您信任的應用程式和使用者分享錯誤報告。"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次再顯示這則訊息"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"錯誤報告"</string>
diff --git a/packages/Shell/res/values-zh-rTW/strings.xml b/packages/Shell/res/values-zh-rTW/strings.xml
index fff73bb..2702bad 100644
--- a/packages/Shell/res/values-zh-rTW/strings.xml
+++ b/packages/Shell/res/values-zh-rTW/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"殼層"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"正在產生錯誤報告 <xliff:g id="ID">#%d</xliff:g>"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"已擷取錯誤報告 <xliff:g id="ID">#%d</xliff:g>"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"錯誤報告 <xliff:g id="ID">#%d</xliff:g> 擷取成功,但螢幕畫面尚未擷取完畢"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"正在新增錯誤報告詳細資訊"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"請稍候…"</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"向左滑動即可分享錯誤報告"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"輕按即可分享錯誤報告"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"輕觸即可分享無螢幕擷圖的錯誤報告;您也可以等候螢幕畫面擷取完畢"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"輕觸即可分享無螢幕擷圖的錯誤報告;您也可以等候螢幕畫面擷取完畢"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"錯誤報告的資料來自系統各個紀錄檔,包括個人和私密資訊。請務必只與您信任的應用程式和使用者分享錯誤報告。"</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次仍顯示這則訊息"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"錯誤報告"</string>
diff --git a/packages/Shell/res/values-zu/strings.xml b/packages/Shell/res/values-zu/strings.xml
index 868de3e..561ac0a 100644
--- a/packages/Shell/res/values-zu/strings.xml
+++ b/packages/Shell/res/values-zu/strings.xml
@@ -19,10 +19,13 @@
     <string name="app_label" msgid="3701846017049540910">"I-Shell"</string>
     <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Umbiko wesiphazamisi ongu-<xliff:g id="ID">#%d</xliff:g> uyacutshungulwa"</string>
     <string name="bugreport_finished_title" msgid="4429132808670114081">"Umbiko wesiphazamisi ongu-<xliff:g id="ID">#%d</xliff:g> uthwetshuliwe"</string>
+    <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Umbiko wesiphazamisi esingu-<xliff:g id="ID">#%d</xliff:g> uthwetshuliwe kodwa isithombe-skrini silindile"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"Ingeza imininingwane kumbiko wesiphazamisi"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"Sicela ulinde..."</string>
     <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swayiphela kwesokunxele ukuze wabelane umbiko wesiphazamiso sakho"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Thepha ukuze wabelane ngombiko wakho wesiphazamisi"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Thepha ukuze wabelane ngombiko wesiphazamisi ngaphandle kwesithombe-skrini noma ulinde isithombe-skrini ukuthi siqede"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Thepha ukuze wabelane ngombiko wesiphazamisi ngaphandle kwesithombe-skrini noma ulinde isithombe-skrini ukuthi siqede"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Imibiko yeziphazamisi iqukethe idatha yamafayela wokungena ahlukile wesistimu, afaka ulwazi lomuntu siqu noma lobumfihlo. Yabelana kuphela ngemibiko yeziphazamisi nezinhlelo zokusebenza nabantu obathembayo."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Bonisa lo mlayezo ngesikhathi esilandelayo"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Imibiko yeziphazamiso"</string>
diff --git a/packages/Shell/res/values/strings.xml b/packages/Shell/res/values/strings.xml
index 38ea880..5d90189 100644
--- a/packages/Shell/res/values/strings.xml
+++ b/packages/Shell/res/values/strings.xml
@@ -20,6 +20,8 @@
     <string name="bugreport_in_progress_title">Bug report <xliff:g id="id">#%d</xliff:g> is being generated</string>
     <!-- Title of notification indicating a bugreport has been successfully captured. [CHAR LIMIT=50] -->
     <string name="bugreport_finished_title">Bug report <xliff:g id="id">#%d</xliff:g> captured</string>
+    <!-- Title of notification indicating a bugreport has been successfully captured, but screenshot is not finished yet. [CHAR LIMIT=50] -->
+    <string name="bugreport_finished_pending_screenshot_title">Bug report <xliff:g id="id">#%d</xliff:g> captured but screenshot pending</string>
     <!-- Title of notification indicating a bugreport is being updated before it can be shared. [CHAR LIMIT=50] -->
     <string name="bugreport_updating_title">Adding details to the bug report</string>
     <!-- Content notification indicating a bugreport is being updated before it can be shared, asking the user to wait [CHAR LIMIT=50] -->
@@ -29,7 +31,10 @@
     <string name="bugreport_finished_text" product="watch">Swipe left to share your bug report</string>
     <!-- Text of notification indicating that tapping will share the captured bugreport. [CHAR LIMIT=100] -->
     <string name="bugreport_finished_text" product="default">Tap to share your bug report</string>
-
+    <!-- Text of notification indicating that swipe left will share the captured bugreport, but giving user the option to wait for the screenshot. [CHAR LIMIT=100] -->
+    <string name="bugreport_finished_pending_screenshot_text" product="watch">Tap to share your bug report without a screenshot or wait for the screenshot to finish</string>
+    <!-- Text of notification indicating that tapping will share the captured bugreport, but giving user the option to wait for the screenshot. [CHAR LIMIT=100] -->
+    <string name="bugreport_finished_pending_screenshot_text" product="default">Tap to share your bug report without a screenshot or wait for the screenshot to finish</string>
 
     <!-- Body of dialog informing user about contents of a bugreport. [CHAR LIMIT=NONE] -->
     <string name="bugreport_confirm">Bug reports contain data from the system\'s various log files, including personal and private information.  Only share bug reports with apps and people you trust.</string>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 1c6a071..7fae0ee 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -454,21 +454,15 @@
         final String name =
                 info.name != null ? info.name : mContext.getString(R.string.bugreport_unnamed);
 
-        final Notification notification = new Notification.Builder(mContext)
-                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+        final Notification notification = newBaseNotification(mContext)
                 .setContentTitle(title)
                 .setTicker(title)
                 .setContentText(name)
                 .setContentInfo(percentText)
                 .setProgress(info.max, info.progress, false)
                 .setOngoing(true)
-                .setLocalOnly(true)
-                .setColor(mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color))
                 .setContentIntent(infoPendingIntent)
-                .addAction(infoAction)
-                .addAction(screenshotAction)
-                .addAction(cancelAction)
+                .setActions(infoAction, screenshotAction, cancelAction)
                 .build();
 
         if (info.finished) {
@@ -620,7 +614,11 @@
      * upon receiving a {@link #INTENT_BUGREPORT_STARTED}.
      */
     private void takeScreenshot(int id, boolean delayed) {
-        MetricsLogger.action(this, MetricsEvent.ACTION_BUGREPORT_NOTIFICATION_ACTION_SCREENSHOT);
+        if (delayed) {
+            // Only logs screenshots requested from the notification action.
+            MetricsLogger.action(this,
+                    MetricsEvent.ACTION_BUGREPORT_NOTIFICATION_ACTION_SCREENSHOT);
+        }
         if (getInfo(id) == null) {
             // Most likely am killed Shell before user tapped the notification. Since system might
             // be too busy anwyays, it's better to ignore the notification and switch back to the
@@ -714,7 +712,7 @@
             if (info.finished) {
                 Log.d(TAG, "Screenshot finished after bugreport; updating share notification");
                 info.renameScreenshots(mScreenshotsDir);
-                sendBugreportNotification(mContext, info);
+                sendBugreportNotification(mContext, info, mTakingScreenshot);
             }
             msg = mContext.getString(R.string.bugreport_screenshot_taken);
         } else {
@@ -803,10 +801,10 @@
         boolean isPlainText = info.bugreportFile.getName().toLowerCase().endsWith(".txt");
         if (!isPlainText) {
             // Already zipped, send it right away.
-            sendBugreportNotification(context, info);
+            sendBugreportNotification(context, info, mTakingScreenshot);
         } else {
             // Asynchronously zip the file first, then send it.
-            sendZippedBugreportNotification(context, info);
+            sendZippedBugreportNotification(context, info, mTakingScreenshot);
         }
     }
 
@@ -903,7 +901,8 @@
     /**
      * Sends a notification indicating the bugreport has finished so use can share it.
      */
-    private static void sendBugreportNotification(Context context, BugreportInfo info) {
+    private static void sendBugreportNotification(Context context, BugreportInfo info,
+            boolean takingScreenshot) {
 
         // Since adding the details can take a while, do it before notifying user.
         addDetailsToZipFile(context, info);
@@ -914,18 +913,22 @@
         shareIntent.putExtra(EXTRA_ID, info.id);
         shareIntent.putExtra(EXTRA_INFO, info);
 
-        final String title = context.getString(R.string.bugreport_finished_title, info.id);
-        final Notification.Builder builder = new Notification.Builder(context)
-                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+        final String title, content;
+        if (takingScreenshot) {
+            title = context.getString(R.string.bugreport_finished_pending_screenshot_title,
+                    info.id);
+            content = context.getString(R.string.bugreport_finished_pending_screenshot_text);
+        } else {
+            title = context.getString(R.string.bugreport_finished_title, info.id);
+            content = context.getString(R.string.bugreport_finished_text);
+        }
+        final Notification.Builder builder = newBaseNotification(context)
                 .setContentTitle(title)
                 .setTicker(title)
-                .setContentText(context.getString(R.string.bugreport_finished_text))
+                .setContentText(content)
                 .setContentIntent(PendingIntent.getService(context, info.id, shareIntent,
                         PendingIntent.FLAG_UPDATE_CURRENT))
-                .setDeleteIntent(newCancelIntent(context, info))
-                .setLocalOnly(true)
-                .setColor(context.getColor(
-                        com.android.internal.R.color.system_notification_accent_color));
+                .setDeleteIntent(newCancelIntent(context, info));
 
         if (!TextUtils.isEmpty(info.name)) {
             builder.setContentInfo(info.name);
@@ -942,28 +945,33 @@
      */
     private static void sendBugreportBeingUpdatedNotification(Context context, int id) {
         final String title = context.getString(R.string.bugreport_updating_title);
-        final Notification.Builder builder = new Notification.Builder(context)
-                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+        final Notification.Builder builder = newBaseNotification(context)
                 .setContentTitle(title)
                 .setTicker(title)
-                .setContentText(context.getString(R.string.bugreport_updating_wait))
+                .setContentText(context.getString(R.string.bugreport_updating_wait));
+        Log.v(TAG, "Sending 'Updating zip' notification for ID " + id + ": " + title);
+        NotificationManager.from(context).notify(TAG, id, builder.build());
+    }
+
+    private static Notification.Builder newBaseNotification(Context context) {
+        return new Notification.Builder(context)
+                .setCategory(Notification.CATEGORY_SYSTEM)
+                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                 .setLocalOnly(true)
                 .setColor(context.getColor(
                         com.android.internal.R.color.system_notification_accent_color));
-        Log.v(TAG, "Sending 'Updating zip' notification for ID " + id + ": " + title);
-        NotificationManager.from(context).notify(TAG, id, builder.build());
     }
 
     /**
      * Sends a zipped bugreport notification.
      */
     private static void sendZippedBugreportNotification(final Context context,
-            final BugreportInfo info) {
+            final BugreportInfo info, final boolean takingScreenshot) {
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
                 zipBugreport(info);
-                sendBugreportNotification(context, info);
+                sendBugreportNotification(context, info, takingScreenshot);
                 return null;
             }
         }.execute();
@@ -1089,7 +1097,14 @@
             preferredDomain = "@" + preferredDomain;
         }
 
-        final Account[] accounts = am.getAccounts();
+        final Account[] accounts;
+        try {
+            accounts = am.getAccounts();
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Could not get accounts for preferred domain " + preferredDomain, e);
+            return null;
+        }
+        if (DEBUG) Log.d(TAG, "Number of accounts: " + accounts.length);
         Account foundAccount = null;
         for (Account account : accounts) {
             if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) {
@@ -1181,14 +1196,13 @@
      * Takes a screenshot and save it to the given location.
      */
     private static boolean takeScreenshot(Context context, String screenshotFile) {
-        ((Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE))
-                .vibrate(150);
         final ProcessBuilder screencap = new ProcessBuilder()
                 .command("/system/bin/screencap", "-p", screenshotFile);
         Log.d(TAG, "Taking screenshot using " + screencap.command());
         try {
             final int exitValue = screencap.start().waitFor();
             if (exitValue == 0) {
+                ((Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE)).vibrate(150);
                 return true;
             }
             Log.e(TAG, "screencap (" + screencap.command() + ") failed: " + exitValue);
@@ -1269,9 +1283,6 @@
                         if (hasFocus) {
                             return;
                         }
-                        // Select-all is useful just initially, since the date-based filename is
-                        // full of hyphens.
-                        mInfoName.setSelectAllOnFocus(false);
                         sanitizeName();
                     }
                 });
diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java
index 9afa900..cbd17bf 100644
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java
@@ -51,6 +51,7 @@
 
     @Override
     public void onReceive(Context context, Intent intent) {
+        Log.d(TAG, "onReceive: " + intent);
         // Clean up older bugreports in background
         cleanupOldFiles(this, intent, INTENT_BUGREPORT_FINISHED, MIN_KEEP_COUNT, MIN_KEEP_AGE);
 
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index a629aac..17f6f6b 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -130,6 +130,9 @@
     private static final boolean RENAMED_SCREENSHOTS = true;
     private static final boolean DIDNT_RENAME_SCREENSHOTS = false;
 
+    private static final boolean PENDING_SCREENSHOT = true;
+    private static final boolean NOT_PENDING_SCREENSHOT = false;
+
     private String mDescription;
 
     private String mPlainTextPath;
@@ -288,6 +291,7 @@
         detailsUi.assertName(NAME);
 
         // Change name - it should have changed system property once focus is changed.
+        detailsUi.focusOnName();
         detailsUi.nameField.setText(NEW_NAME);
         detailsUi.focusAwayFromName();
         assertPropertyValue(NAME_PROPERTY, NEW_NAME);
@@ -409,9 +413,8 @@
 
         sendBugreportStarted(ID2, PID2, NAME2, 1000);
 
-        Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mZipPath, mScreenshotPath);
-        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
-                NEW_NAME, TITLE, DESCRIPTION, 1, RENAMED_SCREENSHOTS);
+        sendBugreportFinished(ID, mZipPath, mScreenshotPath);
+        Bundle extras = acceptBugreportAndGetSharedIntent(ID, PENDING_SCREENSHOT);
 
         detailsUi = new DetailsUi(mUiBot, ID2);
         detailsUi.assertName(NAME2);
@@ -602,7 +605,7 @@
     private Bundle sendBugreportFinishedAndGetSharedIntent(int id, String bugreportPath,
             String screenshotPath) {
         sendBugreportFinished(id, bugreportPath, screenshotPath);
-        return acceptBugreportAndGetSharedIntent(id);
+        return acceptBugreportAndGetSharedIntent(id, NOT_PENDING_SCREENSHOT);
     }
 
     /**
@@ -611,7 +614,11 @@
      * @return extras sent in the shared intent.
      */
     private Bundle acceptBugreportAndGetSharedIntent(int id) {
-        acceptBugreport(id);
+        return acceptBugreportAndGetSharedIntent(id, NOT_PENDING_SCREENSHOT);
+    }
+
+    private Bundle acceptBugreportAndGetSharedIntent(int id, boolean pendingScreenshot) {
+        acceptBugreport(id, pendingScreenshot);
         mUiBot.chooseActivity(UI_NAME);
         return mListener.getExtras();
     }
@@ -627,7 +634,13 @@
      * Accepts the notification to share the finished bugreport.
      */
     private void acceptBugreport(int id) {
-        mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title, id));
+        acceptBugreport(id, NOT_PENDING_SCREENSHOT);
+    }
+
+    private void acceptBugreport(int id, boolean pendingScreenshot) {
+        final int res = pendingScreenshot ? R.string.bugreport_finished_pending_screenshot_title
+                : R.string.bugreport_finished_title;
+        mUiBot.clickOnNotification(mContext.getString(res, id));
     }
 
     /**
@@ -954,40 +967,44 @@
             cancelButton = mUiBot.getObjectById("android:id/button2");
         }
 
-        private void assertField(String name, UiObject field, String expected) {
-            try {
-                String actual = field.getText().toString();
-                assertEquals("Wrong value on field '" + name + "'", expected, actual);
-            } catch (UiObjectNotFoundException e) {
-                // Should not happen...
-                throw new IllegalStateException("field not found: " + name, e);
-            }
+        private void assertField(String name, UiObject field, String expected)
+                throws UiObjectNotFoundException {
+            String actual = field.getText().toString();
+            assertEquals("Wrong value on field '" + name + "'", expected, actual);
         }
 
-        void assertName(String expected) {
+        void assertName(String expected) throws UiObjectNotFoundException {
             assertField("name", nameField, expected);
         }
 
-        void assertTitle(String expected) {
+        void assertTitle(String expected) throws UiObjectNotFoundException {
             assertField("title", titleField, expected);
         }
 
-        void assertDescription(String expected) {
+        void assertDescription(String expected) throws UiObjectNotFoundException {
             assertField("description", descField, expected);
         }
 
         /**
+         * Set focus on the name field so it can be validated once focus is lost.
+         */
+        void focusOnName() throws UiObjectNotFoundException {
+            mUiBot.click(nameField, "name_field");
+            assertTrue("name_field not focused", nameField.isFocused());
+        }
+
+        /**
          * Takes focus away from the name field so it can be validated.
          */
-        void focusAwayFromName() {
+        void focusAwayFromName() throws UiObjectNotFoundException {
             mUiBot.click(titleField, "title_field"); // Change focus.
             mUiBot.pressBack(); // Dismiss keyboard.
+            assertFalse("name_field is focused", nameField.isFocused());
         }
 
         void reOpen() {
             openProgressNotification(ID);
             mUiBot.click(detailsButton, "details_button");
-
         }
 
         void clickOk() {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 637551c..334035c 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -187,6 +187,15 @@
             android:process=":screenshot"
             android:exported="false" />
 
+        <!-- Called from PhoneWindowManager -->
+        <receiver android:name=".screenshot.ScreenshotServiceErrorReceiver"
+            android:process=":screenshot"
+            android:exported="false">
+            <intent-filter>
+                <action android:name="com.android.systemui.screenshot.SHOW_ERROR" />
+            </intent-filter>
+        </receiver>
+
         <service android:name=".LoadAverageService"
                 android:exported="true" />
 
diff --git a/packages/SystemUI/res/drawable/recents_empty.xml b/packages/SystemUI/res/drawable/recents_empty.xml
new file mode 100644
index 0000000..5506de1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/recents_empty.xml
@@ -0,0 +1,43 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="100dp"
+    android:height="132dp"
+    android:viewportWidth="100"
+    android:viewportHeight="132">
+
+    <path
+        android:fillColor="#5AFFFFFF"
+        android:pathData="M86.91,68.67H13.09c-4.96,0-9,4.04-9,9V119c0,4.96,4.04,9,9,9h73.82c4.96,0,9-4.04,9-9V77.67
+C95.91,72.7,91.87,68.67,86.91,68.67z M27.59,77.27h26.72v3.94H27.59V77.27z
+M18.73,74.74c2.49,0,4.5,2.01,4.5,4.5
+c0,2.49-2.01,4.5-4.5,4.5s-4.5-2.01-4.5-4.5C14.23,76.75,16.24,74.74,18.73,74.74z
+M89.91,119c0,1.65-1.35,3-3,3H13.09 c-1.65,0-3-1.35-3-3V88.67h79.82V119z" />
+    <path
+        android:fillColor="#5AFFFFFF"
+        android:pathData="M86.91,36.3H13.09c-4.96,0-9,4.04-9,9v23c1.65-1.58,3.71-2.73,6-3.28v-9.08h79.82v9.08
+c2.29,0.55,4.35,1.69,6,3.28v-23C95.91,40.34,91.87,36.3,86.91,36.3z
+M18.73,51.38c-2.49,0-4.5-2.01-4.5-4.5s2.01-4.5,4.5-4.5
+s4.5,2.01,4.5,4.5S21.22,51.38,18.73,51.38z M54.31,48.84H27.59v-3.94h26.72V48.84z" />
+    <path
+        android:fillColor="#5AFFFFFF"
+        android:pathData="M86.91,4H13.09c-4.96,0-9,4.04-9,9v22.94c1.65-1.58,3.71-2.73,6-3.28V24h79.82v8.67
+c2.29,0.55,4.35,1.69,6,3.28V13C95.91,8.04,91.87,4,86.91,4z
+M18.73,18.5c-2.49,0-4.5-2.01-4.5-4.5s2.01-4.5,4.5-4.5
+s4.5,2.01,4.5,4.5S21.22,18.5,18.73,18.5z M54.31,15.97H27.59v-3.94h26.72V15.97z" />
+    <path
+        android:pathData="M 0 0 H 100 V 132 H 0 V 0 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_customize_panel.xml b/packages/SystemUI/res/layout/qs_customize_panel.xml
index 0491ea0..7af247e 100644
--- a/packages/SystemUI/res/layout/qs_customize_panel.xml
+++ b/packages/SystemUI/res/layout/qs_customize_panel.xml
@@ -24,26 +24,4 @@
     android:background="@drawable/qs_customizer_background"
     android:gravity="center_horizontal">
 
-    <Toolbar
-        android:id="@*android:id/action_bar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="28dp"
-        android:navigationContentDescription="@*android:string/action_bar_up_description"
-        style="?android:attr/toolbarStyle" />
-
-    <android.support.v7.widget.RecyclerView
-        android:id="@android:id/list"
-        android:layout_width="@dimen/notification_panel_width"
-        android:layout_height="0dp"
-        android:layout_weight="1"
-        android:scrollIndicators="top"
-        android:scrollbars="vertical" />
-
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/navigation_bar_size"
-        android:layout_gravity="bottom"
-        android:background="#ff000000" />
-
 </com.android.systemui.qs.customize.QSCustomizer>
diff --git a/packages/SystemUI/res/layout/qs_customize_panel_content.xml b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
new file mode 100644
index 0000000..75f8fa4
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 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.
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <Toolbar
+        android:id="@*android:id/action_bar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="28dp"
+        android:navigationContentDescription="@*android:string/action_bar_up_description"
+        style="?android:attr/toolbarStyle" />
+
+    <android.support.v7.widget.RecyclerView
+        android:id="@android:id/list"
+        android:layout_width="@dimen/notification_panel_width"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:scrollIndicators="top"
+        android:scrollbars="vertical" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/navigation_bar_size"
+        android:layout_gravity="bottom"
+        android:background="#ff000000" />
+</merge>
diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml
index df46271..c062b6d 100644
--- a/packages/SystemUI/res/layout/qs_detail_header.xml
+++ b/packages/SystemUI/res/layout/qs_detail_header.xml
@@ -30,6 +30,7 @@
         android:padding="16dp"
         android:clickable="true"
         android:background="?android:attr/selectableItemBackground"
+        android:contentDescription="@*android:string/action_bar_up_description"
         android:src="?android:attr/homeAsUpIndicator" />
 
     <TextView
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index b2c0331..53d9cc5 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -16,10 +16,12 @@
 
 <TextView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
     android:layout_gravity="center"
     android:gravity="center"
+    android:drawableTop="@drawable/recents_empty"
+    android:drawablePadding="25dp"
     android:textSize="16sp"
     android:textColor="#ffffffff"
     android:text="@string/recents_empty_message"
diff --git a/packages/SystemUI/res/layout/tv_pip_onboarding.xml b/packages/SystemUI/res/layout/tv_pip_onboarding.xml
index f031bb4..b0814cf 100644
--- a/packages/SystemUI/res/layout/tv_pip_onboarding.xml
+++ b/packages/SystemUI/res/layout/tv_pip_onboarding.xml
@@ -37,10 +37,13 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="24dp"
+        android:paddingStart="24dp"
+        android:paddingEnd="24dp"
         android:fontFamily="sans-serif"
         android:textSize="16sp"
         android:textColor="#EEEEEE"
         android:lineSpacingMultiplier="1.28"
+        android:gravity="top|center_horizontal"
         android:text="@string/pip_onboarding_description" />
     <Button
         android:id="@+id/close"
diff --git a/packages/SystemUI/res/layout/tv_pip_overlay.xml b/packages/SystemUI/res/layout/tv_pip_overlay.xml
index 40c6fa1..1ba423b 100644
--- a/packages/SystemUI/res/layout/tv_pip_overlay.xml
+++ b/packages/SystemUI/res/layout/tv_pip_overlay.xml
@@ -24,13 +24,19 @@
     <TextView
         android:id="@+id/guide_overlay"
         android:layout_width="match_parent"
-        android:layout_height="32dp"
+        android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
+        android:paddingTop="6dp"
+        android:paddingBottom="6dp"
+        android:paddingStart="10dp"
+        android:paddingEnd="10dp"
         android:textSize="14sp"
         android:textColor="#EEEEEE"
         android:fontFamily="sans-serif"
         android:background="@drawable/tv_pip_overlay_background"
+        android:lineSpacingMultiplier="1.465"
         android:gravity="center"
+        android:maxLines="2"
         android:text="@string/pip_hold_home" />
     <LinearLayout
         android:id="@+id/guide_buttons"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 30d9ed7..090b8e6 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Skermkiekie geneem."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Raak om jou skermkiekie te sien."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Kon nie skermkiekie neem nie."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Kon nie skermkiekie stoor nie."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan weens beperkte bergingspasie nie skermkiekie stoor nie."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Die program of jou organisasie laat nie toe dat skermkiekies geneem word nie."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-lêeroordrag-opsies"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Werkmodus is aan."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Werkmodus is afgeskakel."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Werkmodus is aangeskakel."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Databespaarder is afgeskakel."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Databespaarder is aangeskakel."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Skermhelderheid"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G-data is laat wag"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data is laat wag"</string>
diff --git a/packages/SystemUI/res/values-af/strings_tv.xml b/packages/SystemUI/res/values-af/strings_tv.xml
new file mode 100644
index 0000000..f595479
--- /dev/null
+++ b/packages/SystemUI/res/values-af/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Maak PIP toe"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Volskerm"</string>
+    <string name="pip_play" msgid="674145557658227044">"Speel"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Laat wag"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Hou "<b>"TUIS"</b>" om PIP te beheer"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Druk en hou die TUIS-knoppie om PIP te beheer"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Het dit"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 9692ae8..e870ea7 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"ቅጽበታዊ ገጽ እይታ ተቀርጿል"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"የእርስዎን ቅጽበታዊ ገጽ እይታ ለማየት ይንኩ"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ቅጽበታዊ ገጽ እይታ መቅረጽ አልተቻለም::"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ቅጽበታዊ ገጽ ዕይታን በማስቀመጥ ጊዜ ችግር አጋጥሟል።"</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ባለው የተገደበ የማከማቻ ቦታ ምክንያት ቅጽበታዊ ገጽ ዕይታን ማስቀመጥ አይችልም።"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ቅጽበታዊ ገጽ እይታዎችን ማንሳት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም።"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"የUSB ፋይል ሰደዳ አማራጮች"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"የሥራ ሁነታ በርቷል።"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"የሥራ ሁነታ ጠፍቷል።"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"የሥራ ሁነታ በርቷል።"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ብሩህነት ያሳዩ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2ጂ-3ጂ ውሂብ ላፍታ ቆሟል"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4ጂ ውሂብ ላፍታ ቆሟል"</string>
diff --git a/packages/SystemUI/res/values-am/strings_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml
new file mode 100644
index 0000000..95e480c
--- /dev/null
+++ b/packages/SystemUI/res/values-am/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIPን ዝጋ"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"ሙሉ ማያ ገጽ"</string>
+    <string name="pip_play" msgid="674145557658227044">"አጫውት"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"ለአፍታ አቁም"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIPን ለመቆጣጠር "<b>"መነሻ"</b>"ን ይያዙ"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PIPን ለመቆጣጠር የመነሻ አዝራሩን ተጭነው ይያዙ"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"ገባኝ"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 181f68b..4a4e004 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -77,6 +77,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"تم التقاط لقطة الشاشة."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"المس لعرض لقطة الشاشة."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"تعذر التقاط لقطة الشاشة."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"حدثت مشكلة أثناء حفظ لقطة الشاشة."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"يتعذر حفظ لقطة الشاشة نظرًا لأن مساحة التخزين المتاحة محدودة."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"غير مسموح بالتقاط لقطات شاشة نظرًا لإذن يتعلق بالتطبيق أو بالمؤسسة."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏خيارات نقل الملفات عبر USB"</string>
@@ -224,6 +225,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"وضع العمل قيد التشغيل."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"تم تعطيل وضع العمل."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"تم تشغيل وضع العمل."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"تم تعطيل توفير البيانات."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"تم تشغيل توفير البيانات."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"سطوع الشاشة"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"بيانات شبكات الجيل الثاني والثالث متوقفة مؤقتًا"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"تم إيقاف بيانات شبكة الجيل الرابع مؤقتًا"</string>
diff --git a/packages/SystemUI/res/values-ar/strings_tv.xml b/packages/SystemUI/res/values-ar/strings_tv.xml
new file mode 100644
index 0000000..a54e0ab
--- /dev/null
+++ b/packages/SystemUI/res/values-ar/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"‏إغلاق PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"ملء الشاشة"</string>
+    <string name="pip_play" msgid="674145557658227044">"تشغيل"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"إيقاف مؤقت"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"‏اضغط "<b>"الرئيسية"</b>" للتحكم في PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"‏اضغط مع الاستمرار على زر الشاشة الرئيسية للتحكم في PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"حسنًا"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 9e88f35..7763cb3 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Skrinşot çəkildi."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Skrinşotunuza baxmaq üçün toxunun"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Skrinşot götürülə bilinmədi."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Skrinşot yadda saxlanarkən problem baş verdi."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Yaddaş ehtiyatının az olması səbəbindən skrinşotu yadda saxlamaq olmur."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Tətbiq və ya təşkilatınız tərəfindən skrinşot çəkməyə icazə verilmir."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB fayl transferi seçimləri"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"İş rejimi aktivdir."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"İş rejimi sönülüdür."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"İş rejimi yanılıdır."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Display brightness"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G məlumatlarına fasilə verildi"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G məlumatlarına fasilə verildi"</string>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings_tv.xml b/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
new file mode 100644
index 0000000..b3ac6d4
--- /dev/null
+++ b/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP bağlayın"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Tam ekran"</string>
+    <string name="pip_play" msgid="674145557658227044">"Göstərin"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Fasilə verin"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP idarı etmək üçün "<b>"Əsas səhifəni"</b>" tutub saxlayın"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PİP nəzarət etmək üçün ƏSAS EKRAN düyməni basıb saxlayın"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Anladım"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 3edc805..fff464d 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -74,6 +74,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Snimak ekrana je napravljen."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Dodirnite da biste videli snimak ekrana."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nije moguće napraviti snimak ekrana."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Došlo je do problema pri čuvanju snimka ekrana."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Čuvanje snimka ekrana nije uspelo zbog ograničenog memorijskog prostora."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikacija ili organizacija ne dozvoljavaju pravljenje snimaka ekrana."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prenosa datoteka"</string>
@@ -221,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Režim rada je uključen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Režim rada je isključen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Režim rada je uključen."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Osvetljenost ekrana"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G podaci su pauzirani"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G podaci su pauzirani"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
new file mode 100644
index 0000000..d78f8d3
--- /dev/null
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Zatvori PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Ceo ekran"</string>
+    <string name="pip_play" msgid="674145557658227044">"Pusti"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pauziraj"</string>
+    <string name="pip_hold_home" msgid="340086535668778109"><b>"POČETNI EKRAN"</b>" kont. PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Pritisnite i zadržite dugme POČETNI EKRAN da biste kontrolisali PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Važi"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 84757b7..876af0a 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Екранната снимка е заснета."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Докоснете, за да видите екранната си снимка."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Екранната снимка не можа да бъде заснета."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"При запазването на екранната снимка възникна проблем."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Екранната снимка не може да се запази поради ограничено място в хранилището."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Правенето на екранни снимки не е разрешено от приложението или организацията ви."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Опции за пренос на файлове чрез USB"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Работният режим е включен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Работният режим е изключен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Работният режим е включен."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Яркост на екрана"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Данните от 2G – 3G са поставени на пауза"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Данните от 4G са поставени на пауза"</string>
diff --git a/packages/SystemUI/res/values-bg/strings_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml
new file mode 100644
index 0000000..c5230a4
--- /dev/null
+++ b/packages/SystemUI/res/values-bg/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Затваряне на PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Цял екран"</string>
+    <string name="pip_play" msgid="674145557658227044">"Пускане"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Пауза"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Контр. на PIP: Задр. "<b>"HOME"</b></string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"За контролиране на PIP натиснете и задръжте бутона „HOME“"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Разбрах"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 18f37e6..eaf450f 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"স্ক্রীনশট নেওয়া হযেছে৷"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"আপনার স্ক্রীনশট দেখতে স্পর্শ করুন৷"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"স্ক্রীনশট নেওয়া যায়নি৷"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"স্ক্রীনশট সংরক্ষণের সময়ে সমস্যা হয়েছে৷"</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"সঞ্চয়স্থান সীমিত থাকায় স্ক্রীনশটটি সংরক্ষণ করা যাবে না৷"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"অ্যাপ্লিকেশান বা আপনার প্রতিষ্ঠান স্ক্রীনশটগুলি নেওয়া অনুমতি দেয়নি৷"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ফাইল স্থানান্তরের বিকল্পগুলি"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"কাজের মোড চালু আছে"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"কাজের মোড বন্ধ আছে।"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"কাজের মোড চালু আছে"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"প্রদর্শনের উজ্জ্বলতা"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ডেটা বিরতি দেওয়া হয়েছে"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ডেটা বিরতি দেওয়া হয়েছে"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings_tv.xml b/packages/SystemUI/res/values-bn-rBD/strings_tv.xml
new file mode 100644
index 0000000..6bb19f5
--- /dev/null
+++ b/packages/SystemUI/res/values-bn-rBD/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP বন্ধ করুন"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"পূর্ণ স্ক্রীন"</string>
+    <string name="pip_play" msgid="674145557658227044">"চালান"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"বিরাম দিন"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP নিয়ন্ত্রণ করতে "<b>"হোম"</b>" কী ধরে রাখুন"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP নিয়ন্ত্রণ করতে HOME বোতামটিকে টিপুন ও ধরে থাকুন"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"বুঝেছি"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index 3a7c6cd..0b72a06 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -74,6 +74,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekran snimljen."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Dodirnite za prikaz snimka ekrana."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Došlo je do greške prilikom snimanja ekrana."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Došlo je do problema prilikom spašavanja snimka ekrana."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snimak ekrana se ne može sačuvati zbog manjka prostora za pohranu."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikacija ili vaša organizacija ne dopuštaju pravljenje snimaka ekrana."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa fajlova"</string>
@@ -221,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Poslovni režim uključen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Poslovni režim je isključen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Poslovni režim je uključen."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Osvjetljenje ekrana"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G prijenos podataka je pauzirano"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G prijenos podataka je pauzirano"</string>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings_tv.xml b/packages/SystemUI/res/values-bs-rBA/strings_tv.xml
new file mode 100644
index 0000000..dd4a518
--- /dev/null
+++ b/packages/SystemUI/res/values-bs-rBA/strings_tv.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Zatvori PIP"</string>
+    <!-- no translation found for pip_fullscreen (8604643018538487816) -->
+    <skip />
+    <!-- no translation found for pip_play (674145557658227044) -->
+    <skip />
+    <!-- no translation found for pip_pause (8412075640017218862) -->
+    <skip />
+    <string name="pip_hold_home" msgid="340086535668778109">"Za kontr. PIP držite "<b>"HOME"</b></string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Za kontrolu PIP, pritisnite i držite dugme POČETAK"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Jasno mi je"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index f8224ac..6ddec67 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"S\'ha fet una captura de pantalla."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Toca per veure la captura de pantalla."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"No s\'ha pogut fer una captura de pantalla."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"S\'ha trobat un problema en desar la captura de pantalla."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"La captura de pantalla no es pot desar perquè no hi ha prou espai d\'emmagatzematge."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"L\'aplicació o l\'organització no permeten fer captures de pantalla."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcions transf. fitxers USB"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"El mode de feina està activat."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"S\'ha desactivat el mode de feina."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"S\'ha activat el mode de feina."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brillantor de la pantalla"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Les dades 2G-3G estan aturades"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Les dades 4G estan aturades"</string>
diff --git a/packages/SystemUI/res/values-ca/strings_tv.xml b/packages/SystemUI/res/values-ca/strings_tv.xml
new file mode 100644
index 0000000..3634b99
--- /dev/null
+++ b/packages/SystemUI/res/values-ca/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Tanca PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reprodueix"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Posa en pausa"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Prem "<b>"INICI"</b>" per controlar PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Mantén premut el botó INICI per controlar PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"D\'acord"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 48c9c55..e23f53f 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -75,6 +75,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky Snímek obrazovky pořízen."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Snímek obrazovky zobrazíte dotykem."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Snímek obrazovky se nepodařilo zachytit."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Při ukládání snímku obrazovky došlo k problému."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snímek obrazovky nelze pořídit kvůli nedostatku místa v úložišti."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikace nebo organizace zakazuje pořizování snímků obrazovky."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti přenosu souborů pomocí rozhraní USB"</string>
@@ -222,6 +223,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Pracovní režim zapnutý"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Pracovní režim je vypnutý."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Pracovní režim je zapnutý."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Spořič dat byl vypnut."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Spořič dat byl zapnut."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Jas displeje"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data 2G a 3G jsou pozastavena"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G jsou pozastavena"</string>
diff --git a/packages/SystemUI/res/values-cs/strings_tv.xml b/packages/SystemUI/res/values-cs/strings_tv.xml
new file mode 100644
index 0000000..b65b08e
--- /dev/null
+++ b/packages/SystemUI/res/values-cs/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Ukončit PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Celá obrazovka"</string>
+    <string name="pip_play" msgid="674145557658227044">"Přehrát"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pozastavit"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Funkci PIP lze ovládat podržením tlačítka "<b>"PLOCHA"</b></string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Funkci PIP lze ovládat podržením tlačítka PLOCHA"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Rozumím"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 50d01ea..ba8898e 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Skærmbilledet er gemt."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Tryk for at se dit skærmbillede."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Skærmbilledet kunne ikke tages."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Der opstod et problem ved lagringen af skærmbilledet."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Skærmbilledet kan ikke gemmes pga. begrænset lagerplads."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Appen eller din organisation tillader ikke, at du tager skærmbilleder."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Muligheder for USB-filoverførsel"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Arbejdstilstand er slået til."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Arbejdstilstand er slået fra."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Arbejdstilstand er slået til."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Skærmens lysstyrke"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G-data er sat på pause"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data er sat på pause"</string>
diff --git a/packages/SystemUI/res/values-da/strings_tv.xml b/packages/SystemUI/res/values-da/strings_tv.xml
new file mode 100644
index 0000000..b51c5df
--- /dev/null
+++ b/packages/SystemUI/res/values-da/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Luk PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Fuld skærm"</string>
+    <string name="pip_play" msgid="674145557658227044">"Afspil"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pause"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" nede for at styre PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Tryk på HOME-knappen, og hold den nede for at styre PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index fd8cf89..345dbed 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot aufgenommen"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Zum Ansehen berühren"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Screenshot konnte nicht aufgenommen werden."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Beim Speichern des Screenshots ist ein Problem aufgetreten."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Speichern des Screenshots aufgrund von zu wenig Speicher nicht möglich."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Die App oder Ihr Unternehmen lässt das Erstellen von Screenshots nicht zu."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-Dateiübertragungsoptionen"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Arbeitsmodus an."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Arbeitsmodus deaktiviert."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Arbeitsmodus aktiviert."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Helligkeit des Displays"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-/3G-Daten pausiert"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-Daten pausiert"</string>
diff --git a/packages/SystemUI/res/values-de/strings_tv.xml b/packages/SystemUI/res/values-de/strings_tv.xml
new file mode 100644
index 0000000..b96669b
--- /dev/null
+++ b/packages/SystemUI/res/values-de/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP schließen"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Vollbild"</string>
+    <string name="pip_play" msgid="674145557658227044">"Wiedergeben"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausieren"</string>
+    <string name="pip_hold_home" msgid="340086535668778109"><b>"STARTBILDSCHIRMTASTE"</b>" drücken, um PIP zu steuern"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Halte die Taste für die Startseite gedrückt, um das Bild-in-Bild zu steuern"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index b5f55d9..78cbb20 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Λήφθηκε το στιγμιότυπο οθόνης ."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Αγγίξτε για να δείτε το στιγμιότυπο οθόνης σας"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Αδύνατη η αποθήκευση του στιγμιότυπου οθόνης."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Παρουσιάστηκε πρόβλημα κατά την αποθήκευση του στιγμιότυπου οθόνης."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Δεν είναι δυνατή η αποθήκευση του στιγμιότυπου οθόνης λόγω περιορισμένου χώρου αποθήκευσης."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Η λήψη στιγμιοτύπων οθόνης δεν επιτρέπεται από την εφαρμογή ή από τον οργανισμό σας."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Επιλογές μεταφοράς αρχείων μέσω USB"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Η λειτουργία εργασίας είναι ενεργή."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Η λειτουργία εργασίας απενεργοποιήθηκε."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Η λειτουργία εργασίας ενεργοποιήθηκε."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Η Εξοικονόμηση δεδομένων είναι ανενεργή."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Η Εξοικονόμηση δεδομένων είναι ενεργή."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Φωτεινότητα οθόνης"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Τα δεδομένα 2G-3G τέθηκαν σε παύση"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Τα δεδομένα 4G τέθηκαν σε παύση"</string>
diff --git a/packages/SystemUI/res/values-el/strings_tv.xml b/packages/SystemUI/res/values-el/strings_tv.xml
new file mode 100644
index 0000000..e72d579
--- /dev/null
+++ b/packages/SystemUI/res/values-el/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Κλείσιμο PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Πλήρης οθόνη"</string>
+    <string name="pip_play" msgid="674145557658227044">"Αναπαραγωγή"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Παύση"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Κρατήστε το πλήκτρο "<b>"HOME"</b>" πατημένο για έλεγχο του PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Πιέστε παρατεταμένα το κουμπί HOME, για να ελέγξετε τη λειτουργία PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Κατάλαβα"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index cbb1ecf..6367ed9 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Touch to view your screenshot."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problem encountered while saving screenshot."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Taking screenshots is not allowed by the app or your organisation."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Work mode on."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Work mode turned off."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Work mode turned on."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Data Saver turned off."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Data Saver turned on."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Display brightness"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G data is paused"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data is paused"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
new file mode 100644
index 0000000..5711c352
--- /dev/null
+++ b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Close PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
+    <string name="pip_play" msgid="674145557658227044">"Play"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pause"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" to control PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Press and hold the HOME button to control PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index cbb1ecf..6367ed9 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Touch to view your screenshot."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problem encountered while saving screenshot."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Taking screenshots is not allowed by the app or your organisation."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Work mode on."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Work mode turned off."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Work mode turned on."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Data Saver turned off."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Data Saver turned on."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Display brightness"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G data is paused"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data is paused"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
new file mode 100644
index 0000000..5711c352
--- /dev/null
+++ b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Close PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
+    <string name="pip_play" msgid="674145557658227044">"Play"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pause"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" to control PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Press and hold the HOME button to control PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index cbb1ecf..6367ed9 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Touch to view your screenshot."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problem encountered while saving screenshot."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Taking screenshots is not allowed by the app or your organisation."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Work mode on."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Work mode turned off."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Work mode turned on."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Data Saver turned off."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Data Saver turned on."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Display brightness"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G data is paused"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data is paused"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
new file mode 100644
index 0000000..5711c352
--- /dev/null
+++ b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Close PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
+    <string name="pip_play" msgid="674145557658227044">"Play"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pause"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" to control PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Press and hold the HOME button to control PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 856c1c1..4769e20 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Se guardó la captura de pantalla."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Toca para ver tu captura de pantalla."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"No se pudo guardar la captura de pantalla."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Se produjo un error al guardar la captura de pantalla."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"No se puede guardar la captura de pantalla debido al almacenamiento limitado."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"La app o tu organización no permiten las capturas de pantalla."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de trabajo activado"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Se desactivó el modo de trabajo."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Se activó el modo de trabajo."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brillo de pantalla"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Datos 2G-3G pausados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Datos 4G pausados"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings_tv.xml b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
new file mode 100644
index 0000000..99913e6
--- /dev/null
+++ b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Cerrar PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reproducir"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Mantén presionado "<b>"INICIO"</b>" para controlar PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Mantén presionado el botón INICIO para controlar PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Entendido"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 4092994..e89125e 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura guardada"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Toca para ver la captura de pantalla"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"No se ha podido guardar la captura de pantalla."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Se ha detectado un problema al guardar la captura de pantalla."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"No se puede guardar la captura de pantalla porque no hay espacio de almacenamiento suficiente."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"La aplicación o tu organización no permiten que se realicen capturas de pantalla."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de trabajo activado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modo de trabajo desactivado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modo de trabajo activado."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brillo de la pantalla"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Datos 2G-3G pausados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Datos 4G pausados"</string>
diff --git a/packages/SystemUI/res/values-es/strings_tv.xml b/packages/SystemUI/res/values-es/strings_tv.xml
new file mode 100644
index 0000000..200410c
--- /dev/null
+++ b/packages/SystemUI/res/values-es/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Cerrar PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reproducir"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Mantén el botón "<b>"INICIO"</b>" pulsado para control de PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Mantén el botón de INICIO pulsado para controlar el modo PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Entendido"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 1279a2c..cad44d9b 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekraanipilt on jäädvustatud."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Puudutage kuvatõmmise vaatamiseks."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Kuvatõmmist ei saanud jäädvustada."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Ekraanipildi salvestamisel ilmnes probleem."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Piiratud salvestusruumi tõttu ei saa ekraanipilti salvestada."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Rakendus või teie organisatsioon ei luba ekraanipilte jäädvustada."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-failiedastuse valikud"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Töörežiim on sees."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Töörežiim on välja lülitatud."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Töörežiim on sisse lülitatud."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ekraani heledus"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G andmekasutus on peatatud"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G andmekasutus on peatatud"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings_tv.xml b/packages/SystemUI/res/values-et-rEE/strings_tv.xml
new file mode 100644
index 0000000..972083b
--- /dev/null
+++ b/packages/SystemUI/res/values-et-rEE/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Sule PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Täisekraan"</string>
+    <string name="pip_play" msgid="674145557658227044">"Esita"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Peata"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP juht. hoidke all nuppu "<b>"AVAEKRAAN"</b></string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP juhtimiseks vajutage pikalt nuppu AVAEKRAAN"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Selge"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 29e3da8..1dc6d68 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Pantaila-argazkia atera da."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Pantaila-argazkia ikusteko, ukitu ezazu."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Ezin izan da pantaila-argazkia atera."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Arazo bat izan da pantaila-argazkia gordetzean."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ezin da atera pantaila-argazkia ez delako tokirik geratzen."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikazioak edo erakundeak ez du onartzen pantaila-argazkiak ateratzea."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB fitxategiak transferitzeko aukerak"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Aktibatuta dago lan modua."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Desaktibatuta dago lan modua."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Aktibatuta dago lan modua."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Bistaratu distira"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G datuen erabilera eten da"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G datuen erabilera eten da"</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings_tv.xml b/packages/SystemUI/res/values-eu-rES/strings_tv.xml
new file mode 100644
index 0000000..a312ea4
--- /dev/null
+++ b/packages/SystemUI/res/values-eu-rES/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Itxi PIPa"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantaila osoa"</string>
+    <string name="pip_play" msgid="674145557658227044">"Erreproduzitu"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausatu"</string>
+    <string name="pip_hold_home" msgid="340086535668778109"><b>"HASIERA"</b>" PIP kontrolatzeko"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Eduki sakatuta hasierako botoia pantaila txikia kontrolatzeko"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Ados"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index cc32518..dfe1d54 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"عکس صفحه‌نمایش گرفته شد."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"برای مشاهده عکس صفحه‌نمایشتان، لمس کنید."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"عکس صفحه‌نمایش گرفته نشد."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"هنگام ذخیره عکس صفحه‌نمایش مشکلی رخ داد."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"به دلیل محدود بودن فضای ذخیره‌سازی نمی‌توانید عکس صفحه‌نمایش را ذخیره کنید."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"این برنامه یا سازمان شما اجازه نمی‌دهند عکس صفحه‌نمایش بگیرید."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏گزینه‌های انتقال فایل USB"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"حالت کار روشن."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"حالت کار خاموش شد."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"حالت کار روشن شد."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"صرفه‌جویی داده خاموش شد."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"صرفه‌جویی داده روشن شد."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"روشنایی نمایشگر"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"‏داده 2G-3G موقتاً متوقف شده است"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"‏داده 4G موقتاً متوقف شده است"</string>
@@ -506,9 +509,9 @@
     <string name="headset" msgid="4534219457597457353">"هدست"</string>
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"هدفون وصل شد"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"هدست وصل شد"</string>
-    <string name="data_saver" msgid="5037565123367048522">"صرفه‌جویی در مصرف داده"</string>
-    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"صرفه‌جویی در مصرف داده روشن است"</string>
-    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"صرفه‌جویی در مصرف داده خاموش است"</string>
+    <string name="data_saver" msgid="5037565123367048522">"صرفه‌جویی داده"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"صرفه‌جویی داده روشن است"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"صرفه‌جویی داده خاموش است"</string>
     <string name="switch_bar_on" msgid="1142437840752794229">"روشن"</string>
     <string name="switch_bar_off" msgid="8803270596930432874">"خاموش"</string>
     <string name="nav_bar" msgid="1993221402773877607">"نوار پیمایش"</string>
diff --git a/packages/SystemUI/res/values-fa/strings_tv.xml b/packages/SystemUI/res/values-fa/strings_tv.xml
new file mode 100644
index 0000000..cf37db1
--- /dev/null
+++ b/packages/SystemUI/res/values-fa/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"‏بستن PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"تمام صفحه"</string>
+    <string name="pip_play" msgid="674145557658227044">"پخش"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"مکث"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"‏کنترل PIP ‏با نگه‌داشتن "<b>"HOME"</b></string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"‏برای کنترل PIP دکمه صفحه اصلی را فشار داده و نگه‌دارید"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"متوجه شدم"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 8b3fb5e..e5d513f 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Kuvakaappaus tallennettu"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Katso kuvakaappaus koskettamalla."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Kuvakaappausta ei voitu tallentaa"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Kuvakaappausta tallennettaessa tapahtui virhe."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kuvakaappauksen tallentaminen epäonnistui, sillä tallennustilaa ei ole riittävästi."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Sovellus tai organisaatiosi ei salli kuvakaappauksien tallentamista."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-tiedostonsiirtoasetukset"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Työtila on käytössä."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Työtila poistettiin käytöstä."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Työtila otettiin käyttöön."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Data Saver poistettiin käytöstä."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Data Saver otettiin käyttöön."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Näytön kirkkaus"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G-tiedonsiirto keskeytettiin"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-tiedonsiirto keskeytettiin"</string>
diff --git a/packages/SystemUI/res/values-fi/strings_tv.xml b/packages/SystemUI/res/values-fi/strings_tv.xml
new file mode 100644
index 0000000..94c7806
--- /dev/null
+++ b/packages/SystemUI/res/values-fi/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Sulje PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Koko näyttö"</string>
+    <string name="pip_play" msgid="674145557658227044">"Toista"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Keskeytä"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP: paina pitkään "<b>"aloituspain"</b>"."</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Hallinnoi PIP-tilaa painamalla ALOITUSNÄYTTÖ-painiketta pitkään."</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Selvä"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index e0beeca..223274f5 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Capture d\'écran réussie"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Appuyez pour afficher votre capture d\'écran."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Impossible de réaliser une capture d\'écran"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Une erreur s\'est produite lors de l\'enregistrement de la saisie d\'écran."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossible d\'enregistrer la saisie d\'écran, car l\'espace de stockage est limité."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"L\'application ou votre organisation n\'autorise pas les saisies d\'écran."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Mode Travail activé."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Le mode Travail est désactivé."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Le mode Travail est activé."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Luminosité de l\'écran"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Données 2G/3G désactivées"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Données 4G désactivées"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
new file mode 100644
index 0000000..48bbb26
--- /dev/null
+++ b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Fermer mode IDI"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Plein écran"</string>
+    <string name="pip_play" msgid="674145557658227044">"Lecture"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Interrompre"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Maint. enf. "<b>"ACC."</b>" pr gér. mode IDI"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 9ef6392..474a240 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Capture d\'écran réussie"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Appuyez pour afficher votre capture d\'écran."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Impossible de réaliser une capture d\'écran"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Erreur lors de l\'enregistrement de la capture d\'écran."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Les captures d\'écran ne sont pas autorisées par l\'application ou par votre organisation."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Mode Travail activé"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Le mode Travail est désactivé."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Le mode Travail est activé."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Luminosité de l\'affichage"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Données 2G-3G désactivées"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Données 4G désactivées"</string>
diff --git a/packages/SystemUI/res/values-fr/strings_tv.xml b/packages/SystemUI/res/values-fr/strings_tv.xml
new file mode 100644
index 0000000..27c62fb
--- /dev/null
+++ b/packages/SystemUI/res/values-fr/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Fermer mode PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Plein écran"</string>
+    <string name="pip_play" msgid="674145557658227044">"Lire"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Suspendre"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Appui long "<b>"ACCUEIL"</b>" pour contrôler PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Appuyez de manière prolongée sur le bouton ACCUEIL pour contrôler le mode PIP."</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index bb85708..a675c21 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de pantalla gardada."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Toca para ver a captura de pantalla."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Non se puido facer a captura de pantalla."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Produciuse un problema ao gardar a captura de pantalla."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Non se pode gardar a captura de pantalla porque o espazo de almacenamento é limitado."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"A aplicación ou a túa organización non permite realizar capturas de pantalla."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcións de transferencia USB"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de traballo activado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Desactivouse o modo de traballo."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Activouse o modo de traballo."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brillo de pantalla"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Os datos 2G-3G están en pausa"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Os datos 4G están en pausa"</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings_tv.xml b/packages/SystemUI/res/values-gl-rES/strings_tv.xml
new file mode 100644
index 0000000..b0343e1
--- /dev/null
+++ b/packages/SystemUI/res/values-gl-rES/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Pechar PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reproducir"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Manter premido "<b>"INICIO"</b>" para controlar PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Mantén premido o botón de INICIO para controlar PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"De acordo"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 075f023..a8394a2 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"સ્ક્રીનશોટ કેપ્ચર કર્યો."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"તમારો સ્ક્રીનશોટ જોવા માટે ટચ કરો."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"સ્ક્રીનશોટ કેપ્ચર કરી શકાયો નથી."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"સ્ક્રીનશૉટ સાચવવામાં સમયા આવી."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"મર્યાદિત સંગ્રહ સ્થાનને કારણે સ્ક્રીનશોટ સાચવી શકાતો નથી."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ઍપ્લિકેશન કે તમારી સંસ્થા દ્વારા સ્ક્રીનશોટ્સ લેવાની મંજૂરી નથી."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ફાઇલ ટ્રાન્સફર વિકલ્પો"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"કાર્ય મોડ ચાલુ."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"કાર્ય મોડ બંધ કર્યો."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"કાર્ય મોડ ચાલુ કર્યો."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"પ્રદર્શન તેજ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ડેટા થોભાવ્યો છે"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ડેટા થોભાવ્યો છે"</string>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings_tv.xml b/packages/SystemUI/res/values-gu-rIN/strings_tv.xml
new file mode 100644
index 0000000..3f2f68a
--- /dev/null
+++ b/packages/SystemUI/res/values-gu-rIN/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP બંધ કરો"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"પૂર્ણ સ્ક્રીન"</string>
+    <string name="pip_play" msgid="674145557658227044">"ચલાવો"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"થોભાવો"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP નિયંત્રિત કરવા માટે "<b>"હોમ"</b>" પકડી રાખો"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP નિયંત્રિત કરવા માટે હોમ બટન દબાવો અને પકડી રાખો"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"સમજાઈ ગયું"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 91a5d69..43331fd 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"स्‍क्रीनशॉट कैप्‍चर किया गया."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"अपना स्‍क्रीनशॉट देखने के लिए स्‍पर्श करें."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रीनशॉट को कैप्चर नहीं किया जा सका."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"स्क्रीनशॉट सहेजते समय समस्या आई"</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"सीमित मेमोरी स्थान के कारण स्क्रीनशॉट सहेजा नहीं जा सकता."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"आपके ऐप्लिकेशन या आपके संगठन द्वारा स्क्रीनशॉट लेने की अनुमति नहीं है."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB फ़ाइल स्थानांतरण विकल्प"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"कार्य मोड चालू है."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"कार्य मोड बंद कर दिया गया."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"कार्य मोड चालू किया गया."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"स्क्रीन की स्क्रीन की रोशनी"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G डेटा रोक दिया गया है"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G डेटा रोक दिया गया है"</string>
diff --git a/packages/SystemUI/res/values-hi/strings_tv.xml b/packages/SystemUI/res/values-hi/strings_tv.xml
new file mode 100644
index 0000000..cf259dd
--- /dev/null
+++ b/packages/SystemUI/res/values-hi/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP बंद करें"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"पूर्ण स्‍क्रीन"</string>
+    <string name="pip_play" msgid="674145557658227044">"चलाएं"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"रोकें"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP नियंत्रण हेतु "<b>"HOME"</b>" होल्ड करें"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP नियंत्रण के लिए HOME बटन को दबाए रखें"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"समझ लिया"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index c7e57de..715f667 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -74,6 +74,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Zaslon je snimljen."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Dodirnite za prikaz snimke zaslona."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nije bilo moguće snimiti zaslon."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Prilikom spremanja snimke zaslona pojavio se problem."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Zaslon nije snimljen zbog ograničenog prostora za pohranu."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Snimanje zaslona ne dopušta aplikacija ili vaša organizacija."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa datoteka"</string>
@@ -221,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Način rada uključen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Način rada isključen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Način rada uključen."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Svjetlina zaslona"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G – 3G podaci pauzirani"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G podaci pauzirani"</string>
diff --git a/packages/SystemUI/res/values-hr/strings_tv.xml b/packages/SystemUI/res/values-hr/strings_tv.xml
new file mode 100644
index 0000000..424c68b
--- /dev/null
+++ b/packages/SystemUI/res/values-hr/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Zatvori PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Cijeli zaslon"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reproduciraj"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pauziraj"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Držite "<b>"POČETNI"</b>" za PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Pritisnite i zadržite tipku POČETNI ZASLON da biste upravljali slikom u slici"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Shvaćam"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 8e55c78..280cdb6 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Képernyőkép rögzítve."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Megérintésével megtekintheti a képernyőképet."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nem sikerült rögzíteni a képernyőképet."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Hiba történt a képernyőkép mentése során."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nem menthet képernyőképet, mert kevés a tárhely."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Az alkalmazás vagy szervezete nem engedélyezi képernyőképek készítését."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-fájlátvitel beállításai"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Munka mód be."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Munka mód kikapcsolva."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Munka mód bekapcsolva."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"A kijelző fényereje"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"A 2G és 3G adatforgalom szünetel."</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"A 4G adatforgalom szünetel"</string>
diff --git a/packages/SystemUI/res/values-hu/strings_tv.xml b/packages/SystemUI/res/values-hu/strings_tv.xml
new file mode 100644
index 0000000..5271a4a
--- /dev/null
+++ b/packages/SystemUI/res/values-hu/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP bezárása"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Teljes képernyő"</string>
+    <string name="pip_play" msgid="674145557658227044">"Lejátszás"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Szüneteltetés"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP vezérlése a "<b>"HOME"</b>"-mal"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"A PIP vezérléséhez tartsa nyomva a HOME gombot"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Rendben"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 09e7f70b..6338d8e 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Էկրանի հանույթը լուսանկարվել է:"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Հպեք ձեր էկրանի հանույթը տեսնելու համար:"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Չհաջողվեց լուսանկարել էկրանի հանույթը:"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Էկրանի պատկերը պահելիս խնդիր առաջացավ:"</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Չհաջողվեց պահել էկրանի պատկերը սահմանափակ հիշողության պատճառով:"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Այս հավելվածը կամ ձեր կազմակերպությունը չի թույլատրում Էկրանի պատկերի ստացումը:"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ֆայլերի փոխանցման ընտրանքներ"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Աշխատանքային ռեժիմը միացված է:"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Աշխատանքային ռեժիմն անջատվեց:"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Աշխատանքային ռեժիմը միացվեց:"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ցուցադրել պայծառությունը"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2Գ-3Գ տվյալների օգտագործումը դադարեցված է"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4Գ տվյալների օգտագործումը դադարեցված է"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings_tv.xml b/packages/SystemUI/res/values-hy-rAM/strings_tv.xml
new file mode 100644
index 0000000..280d733
--- /dev/null
+++ b/packages/SystemUI/res/values-hy-rAM/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Փակել PIP-ն"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Լիէկրան"</string>
+    <string name="pip_play" msgid="674145557658227044">"Նվագարկել"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Դադարեցնել"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP-ն կառավարելու համար սեղմած պահեք "<b>"HOME"</b>" կոճակը"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP-ն կառավարելու համար սեղմեք և պահեք HOME կոճակը"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Պարզ է"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 46340a7..7723663 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Tangkapan layar diambil."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Sentuh untuk melihat tangkapan layar Anda."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Tidak dapat mengambil tangkapan layar."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Terjadi masalah saat menyimpan tangkapan layar."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Tidak dapat menyimpan tangkapan layar karena ruang penyimpanan terbatas."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Mengambil tangkapan layar tidak diizinkan oleh aplikasi atau organisasi."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opsi transfer file USB"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Mode kerja aktif."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Mode kerja dinonaktifkan."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Mode kerja diaktifkan."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Penghemat Data nonaktif."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Penghemat Data diaktifkan."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Kecerahan tampilan"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data 2G-3G dijeda"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G dijeda"</string>
diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml
new file mode 100644
index 0000000..c12fa9c
--- /dev/null
+++ b/packages/SystemUI/res/values-in/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Tutup PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Layar penuh"</string>
+    <string name="pip_play" msgid="674145557658227044">"Putar"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Jeda"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Tahan "<b>"LAYAR UTAMA"</b>" untuk mengontrol PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Tekan dan tahan tombol LAYAR UTAMA untuk mengontrol PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Mengerti"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 89708de..57756e0 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Skjámynd var tekin."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Snertu til að skoða skjámyndina."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Ekki tókst að taka skjámynd."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Upp kom vandamál við að vista skjámynd."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ekki tókst að vista skjámynd vegna takmarkaðs geymslupláss."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Forritið eða fyrirtækið þitt leyfir ekki að teknar séu skjámyndir."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Valkostir USB-skráaflutnings"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Kveikt á vinnustillingu."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Slökkt á vinnustillingu."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Kveikt á vinnustillingu."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Slökkt var á gagnasparnaði."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Kveikt var á gagnasparnaði."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Birtustig skjás"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Slökkt er á 2G- og 3G-gögnum"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Slökkt er á 4G-gögnum"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings_tv.xml b/packages/SystemUI/res/values-is-rIS/strings_tv.xml
new file mode 100644
index 0000000..9c3db2f
--- /dev/null
+++ b/packages/SystemUI/res/values-is-rIS/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Loka mynd í mynd"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Allur skjárinn"</string>
+    <string name="pip_play" msgid="674145557658227044">"Spila"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Hlé"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Haltu "<b>"HOME"</b>"-hnappinum inni til að stjórna innfelldri mynd"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Haltu „Home“-hnappinum inni til að stjórna innfelldri mynd"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Ég skil"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index aa6dd28..b4f473a 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot acquisito."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Tocca per visualizzare il tuo screenshot."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Impossibile acquisire lo screenshot."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Si è verificato un problema durante il salvataggio dello screenshot."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossibile salvare lo screenshot a causa dello spazio di archiviazione limitato."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"L\'acquisizione di screenshot non è consentita dall\'app o dall\'organizzazione."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opzioni trasferimento file USB"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modalità Lavoro attiva."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modalità Lavoro disattivata."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modalità Lavoro attivata."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Luminosità dello schermo"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Dati 2G-3G sospesi"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Dati 4G sospesi"</string>
diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml
new file mode 100644
index 0000000..dc79802
--- /dev/null
+++ b/packages/SystemUI/res/values-it/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Chiudi PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Schermo intero"</string>
+    <string name="pip_play" msgid="674145557658227044">"Riproduci"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausa"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Tieni premuto "<b>"HOME"</b>" per controllare PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Tieni premuto il pulsante HOME per controllare PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index ed44624..2ace8e8 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -75,6 +75,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"צילום המסך בוצע."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"גע כדי להציג את צילום המסך שלך"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"לא ניתן לבצע צילום מסך."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"התגלתה בעיה בשמירת צילום מסך."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"לא ניתן לשמור צילום מסך עקב שטח אחסון מוגבל."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"האפליקציה, או הארגון שלך, אינם מתירים לבצע צילומי מסך."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏אפשרויות העברת קבצים ב-USB"</string>
@@ -222,6 +223,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"מצב עבודה מופעל."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"מצב עבודה הושבת."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"מצב עבודה הופעל."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"בהירות תצוגה"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"‏השימוש בנתוני 2G-3G מושהה"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"‏השימוש בנתוני 4G מושהה"</string>
diff --git a/packages/SystemUI/res/values-iw/strings_tv.xml b/packages/SystemUI/res/values-iw/strings_tv.xml
new file mode 100644
index 0000000..77deaf6
--- /dev/null
+++ b/packages/SystemUI/res/values-iw/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"‏סגור PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"מסך מלא"</string>
+    <string name="pip_play" msgid="674145557658227044">"הפעל"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"השהה"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"‏לחץ לחיצה ארוכה על "<b>"דף הבית"</b>" כדי לשלוט ב-PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"‏לחץ לחיצה ממושכת על לחצן דף הבית כדי לשלוט ב-PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"הבנתי"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 8fda706..27bb232 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"スクリーンショットを取得しました。"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"タップしてスクリーンショットを表示します。"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"スクリーンショットをキャプチャできませんでした。"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"スクリーンショットの保存中に問題が発生しました。"</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"空き容量が足りないため、スクリーンショットを保存できません。"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"アプリまたは組織によって許可されていないため、スクリーンショットは撮れません。"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USBファイル転送オプション"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Work モードがオンです。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Work モードをオフにしました。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Work モードをオンにしました。"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ディスプレイの明るさ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G~3Gデータは一時停止中です"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4Gデータは一時停止中です"</string>
diff --git a/packages/SystemUI/res/values-ja/strings_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml
new file mode 100644
index 0000000..e045fd6
--- /dev/null
+++ b/packages/SystemUI/res/values-ja/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP を閉じる"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"全画面表示"</string>
+    <string name="pip_play" msgid="674145557658227044">"再生"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"一時停止"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP を管理するには ["<b>"ホーム"</b>"] を押し続けます"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"閉じる"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index b365eb3..14f9406 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"სკრინშოტი გადაღებულია."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"შეეხეთ ეკრანის სურათის სანახავად."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ვერ მოხერხდა ეკრანის ანაბეჭდის გადაღება."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ეკრანის ანაბეჭდის შენახვისას წარმოიქმნა პრობლემა."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა შეზღუდული მეხსიერების გამო."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ეკრანის ანაბეჭდების შექმნა არ არის ნებადართული აპის ან თქვენი ორგანიზაციის მიერ."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ფაილის ტრანსფერის პარამეტრები"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"სამსახურის რეჟიმი ჩართულია."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"სამსახურის რეჟიმი გამორთულია."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"სამსახურის რეჟიმი ჩართულია."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"მონაცემთა დამზოგველი გამორთულია."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"მონაცემთა დამზოგველი ჩართულია."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"ეკრანის სიკაშკაშე"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G მონაცემები შეჩერებულია"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G მონაცემები შეჩერებულია"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings_tv.xml b/packages/SystemUI/res/values-ka-rGE/strings_tv.xml
new file mode 100644
index 0000000..e525eba
--- /dev/null
+++ b/packages/SystemUI/res/values-ka-rGE/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP-ის დახურვა"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"სრულ ეკრანზე"</string>
+    <string name="pip_play" msgid="674145557658227044">"დაკვრა"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"პაუზა"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP-ის სამართავად, გეჭიროთ "<b>"მთავარ ღილაკზე"</b></string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP-ის სამართავად, ხანგრძლივად დააჭირეთ მთავარ ღილაკს"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"გასაგებია"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 720caec..07c95c8 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот сақталды."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Скриншотты көру үшін түрту."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Скриншот жасалмады."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Скриншотты сақтау кезінде мәселе орын алды."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Жадтағы шектеулі бос орынға байланысты скриншотты сақтау мүмкін емес."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Қолданба немесе ұйым скриншоттар түсіруге рұқсат етпейді."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB файлын жіберу опциялары"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Жұмыс режимі қосулы."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Жұмыс режимі өшірілді."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Жұмыс режимі қосылды."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Дерек сақтағыш өшірілді."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Дерек сақтағыш қосылды."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Дисплей жарықтығы"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G деректері кідіртілді"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G деректері кідіртілді"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml b/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml
new file mode 100644
index 0000000..e7e7bfd
--- /dev/null
+++ b/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP жабу"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Толық экран"</string>
+    <string name="pip_play" msgid="674145557658227044">"Ойнату"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Кідірту"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP басқару үшін "<b>"HOME"</b>" басып тұрыңыз"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP функциясын басқару үшін НЕГІЗГІ БЕТ түймесін басып тұрыңыз"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Түсіндім"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 97772ad..cafa329 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"បាន​ចាប់​យក​រូបថត​អេក្រង់។​"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"ប៉ះ ​ដើម្បី​មើល​រូបថត​អេក្រង់​របស់​អ្នក​។"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"មិន​អាច​ចាប់​យក​រូប​ថត​អេក្រង់​។"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"បានជួបប្រទះបញ្ហាខណៈពេលរក្សាទុកការថតអេក្រង់"</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"មិនអាចរក្សាទុករូបថតអេក្រង់បានទេដោយសារទំហំផ្ទុកមានកម្រិត។"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ការថតរូបអេក្រង់មិនត្រូវបានអនុញ្ញាតដោយកម្មវិធីនេះ ឬស្ថាប័នរបស់អ្នក។"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"ជម្រើស​ផ្ទេរ​ឯកសារ​តាម​យូអេសប៊ី"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"បើករបៀបការងារ"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"បានបិទរបៀបការងារ"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"បានបើករបៀបការងារ"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ពន្លឺ​ការ​បង្ហាញ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"ទិន្នន័យ 2G-3G ត្រូវបានផ្អាក"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"ទិន្នន័យ 4G ត្រូវបានផ្អាក"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings_tv.xml b/packages/SystemUI/res/values-km-rKH/strings_tv.xml
new file mode 100644
index 0000000..2d40468
--- /dev/null
+++ b/packages/SystemUI/res/values-km-rKH/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"បិទ PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"ពេញអេក្រង់"</string>
+    <string name="pip_play" msgid="674145557658227044">"ចាក់"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"ផ្អាក"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"សង្កត់ប៊ូតុង "<b>"ដើម"</b>" ដើម្បីគ្រប់គ្រង PIP"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"យល់ហើយ"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 481b918c..11d239c 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಸೆರೆಹಿಡಿಯಲಾಗಿದೆ."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ವೀಕ್ಷಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಸೆರೆಹಿಡಿಯಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸುವಲ್ಲಿ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ಪರಿಮಿತ ಸಂಗ್ರಹಣೆ ಸ್ಥಳದ ಕಾರಣದಿಂದಾಗಿ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳುವುದನ್ನು ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ನಿಮ್ಮ ಸಂಸ್ಥೆ ಅನುಮತಿಸುವುದಿಲ್ಲ."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ಫೈಲ್ ವರ್ಗಾವಣೆ ಆಯ್ಕೆಗಳು"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"ಕೆಲಸದ ಮೋಡ್ ಆನ್ ಆಗಿದೆ."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"ಕೆಲಸದ ಮೋಡ್ ಆಫ್ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"ಕೆಲಸದ ಮೋಡ್ ಆನ್ ಮಾಡಲಾಗಿದೆ."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ಹೊಳಪನ್ನು ಪ್ರದರ್ಶಿಸಿ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ಡೇಟಾವನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ಡೇಟಾ ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings_tv.xml b/packages/SystemUI/res/values-kn-rIN/strings_tv.xml
new file mode 100644
index 0000000..5ed7705
--- /dev/null
+++ b/packages/SystemUI/res/values-kn-rIN/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP ಮುಚ್ಚಿ"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"ಪೂರ್ಣ ಪರದೆ"</string>
+    <string name="pip_play" msgid="674145557658227044">"ಪ್ಲೇ"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"ವಿರಾಮ"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP ನಿಯಂತ್ರಿಸಲು "<b>"HOME"</b>" ಕೀಯನ್ನು ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP ನಿಯಂತ್ರಿಸಲು HOME ಬಟನ್ ಒತ್ತಿರಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"ಅರ್ಥವಾಯಿತು"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index a3f4ff1..30d4216 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"캡쳐화면 저장됨"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"캡쳐화면을 보려면 터치하세요."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"캡쳐화면을 캡쳐하지 못했습니다."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"스크린샷을 저장하는 중 문제가 발생했습니다."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"저장용량이 부족하여 스크린샷을 저장할 수 없습니다."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"앱이나 조직에서 스크린샷 촬영을 허용하지 않습니다."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB 파일 전송 옵션"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"작업 모드가 사용 설정되었습니다."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"작업 모드가 사용 중지되었습니다."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"작업 모드가 사용 설정되었습니다."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"디스플레이 밝기"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G 데이터 사용 중지됨"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G 데이터 사용 중지됨"</string>
diff --git a/packages/SystemUI/res/values-ko/strings_tv.xml b/packages/SystemUI/res/values-ko/strings_tv.xml
new file mode 100644
index 0000000..2846e55
--- /dev/null
+++ b/packages/SystemUI/res/values-ko/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP 닫기"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"전체화면"</string>
+    <string name="pip_play" msgid="674145557658227044">"재생"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"일시중지"</string>
+    <string name="pip_hold_home" msgid="340086535668778109"><b>"HOME"</b>"을 눌러 PIP 제어"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"확인"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 96ffa96..653dded 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот тартылды."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Тийип, скриншотту көрүңүз."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Скриншот кылынбай жатат."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Скриншотту сактоо учурунда көйгөй чыкты."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Сактагычта бош орун аз болгондуктан скриншот сакталбай жатат."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Скриншот тартууга колдонмо же ишканаңыз уруксат бербейт."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB менен файл өткөрүү мүмкүнчүлүктөрү"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Иштөө режими күйүк."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Иштөө режими өчүрүлдү."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Иштөө режими күйгүзүлдү."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Дайындарды үнөмдөгүч өчүрүлдү."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Дайындарды үнөмдөгүч күйгүзүлдү."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Жарыктыгын көрсөтүү"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G дайындары тындырылды."</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G дайындары тындырылды"</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings_tv.xml b/packages/SystemUI/res/values-ky-rKG/strings_tv.xml
new file mode 100644
index 0000000..2da47ea
--- /dev/null
+++ b/packages/SystemUI/res/values-ky-rKG/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP\'ти жабуу"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Толук экран"</string>
+    <string name="pip_play" msgid="674145557658227044">"Ойнотуу"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Тындыруу"</string>
+    <string name="pip_hold_home" msgid="340086535668778109"><b>"БАШКЫ БЕТ"</b>" басып туруп PIP\'ти башкарыңыз"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP көзөмөлдөө үчүн БАШКЫ БЕТ баскычын басып, кармап туруңуз"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Түшүндүм"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index 26a81c8..585984c 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -22,6 +22,9 @@
     <!-- Standard notification gravity -->
     <integer name="notification_panel_layout_gravity">@integer/standard_notification_panel_layout_gravity</integer>
 
+    <!-- The size of the initial peek area at the bottom of the stack (above the nav bar). -->
+    <dimen name="recents_initial_bottom_peek_size">@dimen/recents_task_bar_height</dimen>
+
     <dimen name="docked_divider_handle_width">2dp</dimen>
     <dimen name="docked_divider_handle_height">16dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 8000621f..80c1e01 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"ຖ່າຍຮູບໜ້າຈໍແລ້ວ"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"ແຕະເພື່ອເບິ່ງພາບໜ້າຈໍຂອງທ່ານ."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ເກີດບັນຫາໃນການບັນທຶກພາບໜ້າຈໍຂອງທ່ານ."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້ເນື່ອງຈາກພື້ນທີ່ຈັດເກັບຂໍ້ມູນມີຈຳກັດ."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ແອັບ ຫຼື ອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ມີການຖ່າຍຮູບໜ້າຈໍ."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ໂຕເລືອກການຍ້າຍໄຟລ໌"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"ໂໝດການເຮັດວຽກເປີດຢູ່."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"ໂໝດການເຮັດວຽກປິດຢູ່."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"ໂໝດການເຮັດວຽກເປີດຢູ່."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"​ຄວາມ​ແຈ້ງ​​ຂອງ​ຈໍ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"ຂໍ້​ມູນ 2G​-3G ຢຸດ​ຊົ່ວ​ຄາວແລ້ວ"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"ຂໍ້​ມູນ 4G ຢຸດ​ຊົ່ວ​ຄາວແລ້ວ"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings_tv.xml b/packages/SystemUI/res/values-lo-rLA/strings_tv.xml
new file mode 100644
index 0000000..e4116f8
--- /dev/null
+++ b/packages/SystemUI/res/values-lo-rLA/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"ປິດ PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"ເຕັມໜ້າຈໍ"</string>
+    <string name="pip_play" msgid="674145557658227044">"ຫຼິ້ນ"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"ຢຸດຊົ່ວຄາວ"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"ກົດ "<b>"HOME"</b>" ຄ້າງໄວ້ເພື່ອຄວບຄຸມ PIP"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"ເຂົ້າໃຈແລ້ວ"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index bb49c39..3c7af5c 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -75,6 +75,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekrano kopija užfiksuota."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Palieskite, kad peržiūrėtumėte ekrano kopiją."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nepavyko užfiksuoti ekrano kopijos."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Išsaugant ekrano kopiją iškilo problemų."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Negalima išsaugoti ekrano kopijos dėl ribotos saugyklos vietos."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Jūsų organizacijoje arba naudojant šią programą neleidžiama daryti ekrano kopijų"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB failo perdavimo parinktys"</string>
@@ -222,6 +223,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Darbo režimas įjungtas."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Darbo režimas išjungtas."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Darbo režimas įjungtas."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ekrano šviesumas"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G duomenys pristabdyti"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G duomenys pristabdyti"</string>
diff --git a/packages/SystemUI/res/values-lt/strings_tv.xml b/packages/SystemUI/res/values-lt/strings_tv.xml
new file mode 100644
index 0000000..8c60970
--- /dev/null
+++ b/packages/SystemUI/res/values-lt/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Uždaryti PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Visas ekranas"</string>
+    <string name="pip_play" msgid="674145557658227044">"Leisti"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pristabdyti"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Kad vald. PIP, pal. pasp. m. "<b>"PAGRINDINIS"</b></string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Jei norite valdyti PIP, paspauskite ir palaikykite pagrindinio puslapio mygtuką"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Supratau"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 574889e..bafad80 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -74,6 +74,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekrānuzņēmums ir uzņemts."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Pieskarieties, lai skatītu ekrānuzņēmumu."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nevarēja uzņemt ekrānuzņēmumu."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Saglabājot ekrānuzņēmumu, radās problēma."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nevar saglabāt ekrānuzņēmumu, jo krātuvē nepietiek vietas."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Lietotne vai jūsu organizācija neatļauj veikt ekrānuzņēmumus."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB failu pārsūtīšanas opcijas"</string>
@@ -221,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Darba režīms ir ieslēgts."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Darba režīms ir izslēgts."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Darba režīms ir ieslēgts."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ekrāna spilgtums"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G datu lietojums ir apturēts"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G datu lietojums ir apturēts"</string>
diff --git a/packages/SystemUI/res/values-lv/strings_tv.xml b/packages/SystemUI/res/values-lv/strings_tv.xml
new file mode 100644
index 0000000..397376a
--- /dev/null
+++ b/packages/SystemUI/res/values-lv/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Aizvērt PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Pilnekrāna režīms"</string>
+    <string name="pip_play" msgid="674145557658227044">"Atskaņot"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Apturēt"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Turiet taustiņu "<b>"SĀKUMS"</b>", lai kontrolētu PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Nospiediet un turiet pogu SĀKUMS, lai kontrolētu PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Labi"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 58b7b75..4902006 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Сликата на екранот е снимена."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Допрете за да ја видите сликата на екранот."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Сликата на екранот не можеше да се сними."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Се појави проблем при зачувување на сликата од екранот."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Сликата од екранот не може да се зачува поради ограничена меморија."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Апликацијата или вашата организација не дозволува создавање слики од екранот."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Пренос на датотека со УСБ"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Режимот на работа е вклучен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Режимот на работа е исклучен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Режимот на работа е вклучен."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Осветленост на екранот"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Податоците 2G-3G се паузирани"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Податоците 4G се паузирани"</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings_tv.xml b/packages/SystemUI/res/values-mk-rMK/strings_tv.xml
new file mode 100644
index 0000000..acb04be
--- /dev/null
+++ b/packages/SystemUI/res/values-mk-rMK/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Затвори PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Цел екран"</string>
+    <string name="pip_play" msgid="674145557658227044">"Пушти"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Пауза"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Задржете "<b>"ДОМА"</b>" за кон. PIP"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Разбрав"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 6627645..9bbc3ad 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"സ്‌ക്രീൻഷോട്ട് എടുത്തു."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"നിങ്ങളുടെ സ്‌ക്രീൻഷോട്ട് കാണാനായി സ്‌പർശിക്കുക."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"സ്‌ക്രീൻഷോട്ട് എടുക്കാൻ കഴിഞ്ഞില്ല."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്ന സമയത്ത് പ്രശ്നം നേരിട്ടു."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"സ്റ്റോറേജ് ഇടം പരിമിതമായതിനാൽ സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കാൻ കഴിയില്ല."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"സ്ക്രീൻഷോട്ടുകൾ എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ഫയൽ കൈമാറൽ ഓപ്‌ഷനുകൾ"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"പ്രവർത്തന മോഡ് ഓണാണ്."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"പ്രവർത്തന മോഡ് ഓഫാക്കി."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"പ്രവർത്തന മോഡ് ഓണാക്കി."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ഡിസ്പ്ലേ തെളിച്ചം"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ഡാറ്റ താൽക്കാലികമായി നിർത്തി"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ഡാറ്റ താൽക്കാലികമായി നിർത്തി"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings_tv.xml b/packages/SystemUI/res/values-ml-rIN/strings_tv.xml
new file mode 100644
index 0000000..3d6250d
--- /dev/null
+++ b/packages/SystemUI/res/values-ml-rIN/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP അടയ്ക്കുക"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"പൂര്‍ണ്ണ സ്ക്രീന്‍"</string>
+    <string name="pip_play" msgid="674145557658227044">"പ്ലേ ചെയ്യുക"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"തൽക്കാലം നിർത്തൂ"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP നിയന്ത്രിക്കാൻ "<b>"ഹോം"</b>" പിടിക്കുക"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"മനസ്സിലായി"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index a69be1f..73df535 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -71,6 +71,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Дэлгэцийн агшинг авсан."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Дэлгэцийн агшныг харах бол хүрнэ үү."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Дэлгэцийн агшинг авч чадсангүй."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Дэлгэцийн агшинг хадгалахад алдаа гарлаа."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Хадгалах сангийн багтаамж бага байгаа тул дэлгэцийн авсан зургийг хадгалах боломжгүй байна."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Дэлгэцийн зураг авахыг апп эсвэл танай байгууллагаас зөвшөөрөөгүй байна."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB файл шилжүүлэх сонголт"</string>
@@ -218,6 +219,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Ажлын горимыг асаасан."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Ажлын горимыг унтраасан."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Ажлын горимыг асаасан."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Дэлгэцийн гэрэлтэлт"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G дата-г түр зогсоосон байна"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G дата-г түр зогсоосон байна"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings_tv.xml b/packages/SystemUI/res/values-mn-rMN/strings_tv.xml
new file mode 100644
index 0000000..334a9f1
--- /dev/null
+++ b/packages/SystemUI/res/values-mn-rMN/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP-г хаах"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Бүтэн дэлгэц"</string>
+    <string name="pip_play" msgid="674145557658227044">"Тоглуулах"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Түр зогсоох"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP-г удирдахын тулд "<b>"HOME"</b>" товчлуурыг дарна уу"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Ойлголоо"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index d99678c..a37365c 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"स्क्रीनशॉट कॅप्चर केला."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"आपला स्क्रीनशॉट पाहण्यासाठी स्पर्श करा."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रीनशॉट कॅप्चर करू शकलो नाही."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"स्क्रीनशॉट जतन करताना समस्या आली."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"मर्यादित संचय जागेमुळे स्क्रीनशॉट जतन करू शकत नाही."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"अॅप किंवा आपल्या संस्थेद्वारे स्क्रीनशॉट घेण्यास अनुमती नाही."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB फाईल स्थानांतरण पर्याय"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"कार्य मोड चालू."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"कार्य मोड बंद केला."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"कार्य मोड चालू केला."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"प्रदर्शन चमक"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G डेटास विराम दिला आहे"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G डेटास विराम दिला आहे"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings_tv.xml b/packages/SystemUI/res/values-mr-rIN/strings_tv.xml
new file mode 100644
index 0000000..2f56b0a
--- /dev/null
+++ b/packages/SystemUI/res/values-mr-rIN/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP बंद करा"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"पूर्ण स्क्रीन"</string>
+    <string name="pip_play" msgid="674145557658227044">"प्ले करा"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"विराम द्या"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP नियंत्रित करण्यासाठी "<b>"मुख्यपृष्ठ"</b>" धरून ठेवा"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP नियंत्रित करण्यासाठी मुख्यपृष्ठ बटण दाबा आणि धरून ठेवा"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"समजले"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index a716eef..e2175e5 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Tangkapan skrin ditangkap."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Sentuh untuk melihat tangkapan skrin anda."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Tidak dapat menangkap tangkapan skrin."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Berlaku masalah semasa menyimpan tangkapan skrin."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Tidak dapat menyimpan tangkapan skrin kerana ruang storan terhad."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Apl atau organisasi anda tidak membenarkan pengambilan tangkapan skrin."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Pilihan pemindahan fail USB"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Mod kerja hidup."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Mod kerja dimatikan."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Mod kerja dihidupkan."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Kecerahan paparan"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data 2G-3G dijeda"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G dijeda"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings_tv.xml b/packages/SystemUI/res/values-ms-rMY/strings_tv.xml
new file mode 100644
index 0000000..83dee5a
--- /dev/null
+++ b/packages/SystemUI/res/values-ms-rMY/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Tutup PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Skrin penuh"</string>
+    <string name="pip_play" msgid="674145557658227044">"Main"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Jeda"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Thn "<b>"SKRN UTMA"</b>" utk kwl PIP"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 503b91f..d6362f3 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား ဖမ်းယူပြီး"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"သင့်ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား ကြည့်ရှုရန် ထိပါ"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား မဖမ်းစီးနိုင်ပါ"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ဖန်သားပြင်ဓာတ်ပုံဖမ်းယူမှုကို သိမ်းဆည်းရာတွင် ပြဿနာကြုံခဲ့သည်။"</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"သိုလှောင်ခန်းနေရာ အကန့်အသတ်ရှိသောကြောင့် ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းဆည်း၍မရပါ။"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ဖန်သားပြင်ဓာတ်ပုံရိုက်ကူးခြင်းကို အက်ပ်မှ သို့မဟုတ် သင့်အဖွဲ့အစည်းမှ ခွင့်မပြုပါ။"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ဖိုင်ပြောင်း ရွေးမှုများ"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"အလုပ် မုဒ်ကို ဖွင့်ထားပါသည်။"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"အလုပ် မုဒ်ကို ပိတ်ထားပါသည်။"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"အလုပ် မုဒ်ကို ဖွင့်ထားပါသည်။"</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"ဒေတာချွေတာမှု ပိတ်ထားသည်။"</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"ဒေတာချွေတာမှု ဖွင့်ထားသည်။"</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"တောက်ပမှုကို ပြရန်"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ဒေတာ ခေတ္တရပ်တန့်သည်"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data ခေတ္တရပ်တန့်သည်"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings_tv.xml b/packages/SystemUI/res/values-my-rMM/strings_tv.xml
new file mode 100644
index 0000000..616acda
--- /dev/null
+++ b/packages/SystemUI/res/values-my-rMM/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP ကိုပိတ်ပါ"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"မျက်နှာပြင် အပြည့်"</string>
+    <string name="pip_play" msgid="674145557658227044">"ဖွင့်ပါ"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"ဆိုင်းငံ့ပါ"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP ကိုထိန်းချုပ်ရန် "<b>"ပင်မ"</b>" ခလုတ်ကို ဖိထားပါ"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP ကိုထိန်းချုပ်ရန် ပင်မခလုတ်ကို နှိပ်ပြီးဖိထားပါ"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"ရပါပြီ"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index b3de239..a2b09c5 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Skjermdumpen er lagret."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Trykk for å se skjermdumpen."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Kan ikke lagre skjermdumpen."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Det oppsto et problem under lagring av skjermdumpen."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan ikke lagre skjermdumpen på grunn av begrenset lagringsplass."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Appen eller organisasjonen din tillater ikke at du tar skjermdumper."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Altern. for USB-filoverføring"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Arbeidsmodusen er på."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Arbeidsmodusen er slått av."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Arbeidsmodusen er slått på."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Lysstyrken på skjermen"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G- og 3G-data er satt på pause"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data er satt på pause"</string>
diff --git a/packages/SystemUI/res/values-nb/strings_tv.xml b/packages/SystemUI/res/values-nb/strings_tv.xml
new file mode 100644
index 0000000..921744e
--- /dev/null
+++ b/packages/SystemUI/res/values-nb/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Lukk PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Fullskjerm"</string>
+    <string name="pip_play" msgid="674145557658227044">"Spill av"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Sett på pause"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Hold inne "<b>"STARTSIDE"</b>" for å kontrollere PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Trykk og hold inne STARTSIDE-knappen for å kontrollere PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Greit"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 2008553..42067ab 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"स्क्रिनसट क्याप्चर गरियो।"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"तपाईँको स्क्रिनसट हेर्न छुनुहोस्।"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रिनसट क्याप्चर गर्न सकिएन।"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"स्क्रिनसटलाई सुरक्षित गर्दा समस्या भयो।"</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"सीमित भण्डारण स्थान उपलब्ध रहेको हुनाले स्क्रिनसटलाई सुरक्षित गर्न सकिँदैन।"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"अनुप्रयोग वा तपाईँको संगठनले स्क्रिनसट लिन अनुमति दॅिंदैन।"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB फाइल सार्ने विकल्पहरू"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"कार्य मोड अन।"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"कार्य मोड बन्द भयो।"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"कार्य मोड सक्रिय भयो।"</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"डेटा सेभरलाई निष्क्रिय पारियो।"</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"डेटा सेभरलाई सक्रिय गरियो।"</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"प्रदर्शन चमक"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G डेटा रोकिएको छ"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G डेटा रोकिएको छ"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings_tv.xml b/packages/SystemUI/res/values-ne-rNP/strings_tv.xml
new file mode 100644
index 0000000..adfb443
--- /dev/null
+++ b/packages/SystemUI/res/values-ne-rNP/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP लाई बन्द गर्नुहोस्"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"पूर्ण स्क्रिन"</string>
+    <string name="pip_play" msgid="674145557658227044">"प्ले गर्नुहोस्"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"रोक्नुहोस्"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP लाई नियन्त्रण गर्न "<b>"गृह"</b>" कुञ्जीलाई थिचिरहनुहोस्"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"IP लाई नियन्त्रण गर्न गृह बटनलाई थिची होल्ड गर्नुहोस्"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"बुझेँ"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 9698cdf..6f15baf 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot gemaakt."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Raak aan om je screenshot te bekijken."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Screenshot is niet gemaakt."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Er is een probleem opgetreden bij het opslaan van het screenshot."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan screenshot niet opslaan vanwege beperkte opslagruimte."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Het maken van screenshots wordt niet toegestaan door de app of je organisatie."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opties voor USB-bestandsoverdracht"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Werkmodus aan."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Werkmodus uitgeschakeld."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Werkmodus ingeschakeld."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Helderheid van het scherm"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G/3G-data zijn onderbroken"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data zijn onderbroken"</string>
diff --git a/packages/SystemUI/res/values-nl/strings_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml
new file mode 100644
index 0000000..8ccf464
--- /dev/null
+++ b/packages/SystemUI/res/values-nl/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP sluiten"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Volledig scherm"</string>
+    <string name="pip_play" msgid="674145557658227044">"Afspelen"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Onderbreken"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Bedien PIP met "<b>"HOME"</b></string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Houd HOME ingedrukt om PIP te bedienen"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 6fb2c70..d07c4d2 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਕੈਪਚਰ ਕੀਤਾ।"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"ਆਪਣਾ ਸਕ੍ਰੀਨਸ਼ੌਟ ਦੇਖਣ ਲਈ ਛੋਹਵੋ।"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਕੈਪਚਰ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕਰਨ ਦੌਰਾਨ ਸਮੱਸਿਆ ਆਈ।"</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ਸੀਮਿਤ ਸਟੋਰੇਜ ਥਾਂ ਦੇ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ।"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਦੁਆਰਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈਣ ਦੀ ਮਨਜ਼ੂਰੀ ਨਹੀਂ ਹੈ।"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਚੋਣਾਂ"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"ਕੰਮ ਮੋਡ ਚਾਲੂ ਹੈ।"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"ਕੰਮ ਮੋਡ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"ਕੰਮ ਮੋਡ ਚਾਲੂ ਕੀਤਾ ਗਿਆ।"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ਡਿਸਪਲੇ ਚਮਕ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ਡਾਟਾ ਰੁਕ ਗਿਆ ਹੈ"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ਡਾਟਾ ਰੁਕ ਗਿਆ ਹੈ"</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings_tv.xml b/packages/SystemUI/res/values-pa-rIN/strings_tv.xml
new file mode 100644
index 0000000..fafcd62
--- /dev/null
+++ b/packages/SystemUI/res/values-pa-rIN/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP ਬੰਦ ਕਰੋ"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"ਪੂਰੀ ਸਕ੍ਰੀਨ"</string>
+    <string name="pip_play" msgid="674145557658227044">"ਚਲਾਓ"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"ਰੋਕੋ"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP ਕੰਟਰੋਲ ਕਰਨ ਲਈ "<b>"ਹੋਮ"</b>" ਦਬਾਈ ਰੱਖੋ"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP ਨੂੰ ਕੰਟਰੋਲ ਕਰਨ ਲਈ ਹੋਮ ਬਟਨ ਨੂੰ ਦੱਬੋ ਅਤੇ ਦਬਾਈ ਰੱਖੋ"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"ਸਮਝ ਲਿਆ"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 974685c..5a4a320 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -75,6 +75,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Wykonano zrzut ekranu."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Dotknij, aby wyświetlić zrzut ekranu."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nie udało się wykonać zrzutu ekranu."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Podczas zapisywania zrzutu ekranu wystąpił błąd."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nie można zapisać zrzutu ekranu, bo brakuje miejsca w pamięci."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Nie możesz wykonać zrzutu ekranu, bo nie zezwala na to aplikacja lub Twoja organizacja."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB – opcje przesyłania plików"</string>
@@ -222,6 +223,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Tryb pracy włączony."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Tryb pracy wyłączony."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Tryb pracy włączony."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Jasność wyświetlacza"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Transmisja danych 2G-3G została wstrzymana"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Transmisja danych 4G została wstrzymana"</string>
diff --git a/packages/SystemUI/res/values-pl/strings_tv.xml b/packages/SystemUI/res/values-pl/strings_tv.xml
new file mode 100644
index 0000000..d0371b0
--- /dev/null
+++ b/packages/SystemUI/res/values-pl/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Zamknij PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Pełny ekran"</string>
+    <string name="pip_play" msgid="674145557658227044">"Odtwórz"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Wstrzymaj"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Przytrzymaj "<b>"EKRAN GŁÓWNY"</b>", by sterować PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Przytrzymaj przycisk EKRAN GŁÓWNY, by sterować PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index ad314e3..089fa75 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de tela obtida."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Toque para visualizar a captura de tela."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter a captura de tela."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problema encontrado ao salvar captura de tela."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível salvar a captura de tela, porque não há espaço suficiente."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Capturas de tela não são permitidas pelo app ou por sua organização."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opções transf. arq. por USB"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de trabalho ativado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modo de trabalho desativado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modo de trabalho ativado."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Economia de dados desativada."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Economia de dados ativada."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brilho da tela"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Os dados 2G e 3G foram pausados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Os dados 4G foram pausados"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
new file mode 100644
index 0000000..36ba02d
--- /dev/null
+++ b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Fechar PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Tela cheia"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reproduzir"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Mantenha "<b>"INÍCIO"</b>" pressionado para controlar o PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Mantenha a tecla \"HOME\" pressionada para controlar o PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Entendi"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 7ee2554..1660670 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de ecrã efetuada"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Toque para ver a captura de ecrã"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter captura de ecrã."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problema encontrado ao guardar a captura de ecrã."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível guardar a captura de ecrã devido a espaço de armazenamento limitado."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"A aplicação ou a sua entidade não tem autorização para tirar capturas de ecrã."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opções de transm. de fich. USB"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de trabalho ativado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"O modo de trabalho foi desativado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"O modo de trabalho foi ativado."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Poupança de dados desativada."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Poupança de dados ativada."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brilho do visor"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Dados 2G-3G em pausa"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Dados 4G em pausa"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
new file mode 100644
index 0000000..b588c7b
--- /dev/null
+++ b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Fechar PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Ecrã inteiro"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reproduzir"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Interromper"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Prima sem soltar o botão "<b>"HOME"</b>" para controlar o PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Prima sem soltar o botão HOME para controlar o PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Compreendi"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index ad314e3..089fa75 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de tela obtida."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Toque para visualizar a captura de tela."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter a captura de tela."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problema encontrado ao salvar captura de tela."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível salvar a captura de tela, porque não há espaço suficiente."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Capturas de tela não são permitidas pelo app ou por sua organização."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opções transf. arq. por USB"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de trabalho ativado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modo de trabalho desativado."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modo de trabalho ativado."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Economia de dados desativada."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Economia de dados ativada."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Brilho da tela"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Os dados 2G e 3G foram pausados"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Os dados 4G foram pausados"</string>
diff --git a/packages/SystemUI/res/values-pt/strings_tv.xml b/packages/SystemUI/res/values-pt/strings_tv.xml
new file mode 100644
index 0000000..36ba02d
--- /dev/null
+++ b/packages/SystemUI/res/values-pt/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Fechar PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Tela cheia"</string>
+    <string name="pip_play" msgid="674145557658227044">"Reproduzir"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Mantenha "<b>"INÍCIO"</b>" pressionado para controlar o PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Mantenha a tecla \"HOME\" pressionada para controlar o PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Entendi"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index c2bec08..b7e0834 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -74,6 +74,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Captură de ecran realizată."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Atingeți pentru a vedea captura de ecran."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Captura de ecran nu a putut fi realizată."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problemă întâmpinată la salvarea capturii de ecran."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Captura de ecran nu poate fi salvată din cauza spațiului de stocare limitat."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Crearea capturilor de ecran nu este permisă de aplicație sau de organizația dvs."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opțiuni pentru transferul de fișiere prin USB"</string>
@@ -221,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modul de lucru este activat."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modul de lucru a fost dezactivat."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modul de lucru a fost activat."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Luminozitatea ecranului"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Conexiunea de date 2G – 3G este întreruptă"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Conexiunea de date 4G este întreruptă"</string>
diff --git a/packages/SystemUI/res/values-ro/strings_tv.xml b/packages/SystemUI/res/values-ro/strings_tv.xml
new file mode 100644
index 0000000..0af2b39
--- /dev/null
+++ b/packages/SystemUI/res/values-ro/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Închideți PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Ecran complet"</string>
+    <string name="pip_play" msgid="674145557658227044">"Redați"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Întrerupeți"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Apăsați lung "<b>"ACASĂ"</b>" pentru a controla PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Apăsați lung butonul ACASĂ pentru a controla PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Am înțeles"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 8ece7fa..f73ebf4 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -75,6 +75,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот сохранен"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Нажмите, чтобы просмотреть"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Не удалось сохранить скриншот."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Не удалось сохранить скриншот."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Не удалось сохранить скриншот: недостаточно места."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Не удалось сделать скриншот: нет разрешения от приложения или организации."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Параметры передачи через USB"</string>
@@ -222,6 +223,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Рабочий режим включен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Рабочий режим отключен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Рабочий режим включен."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Яркость экрана"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Передача данных 2G и 3G приостановлена"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Передача данных 4G приостановлена"</string>
diff --git a/packages/SystemUI/res/values-ru/strings_tv.xml b/packages/SystemUI/res/values-ru/strings_tv.xml
new file mode 100644
index 0000000..30f55cb
--- /dev/null
+++ b/packages/SystemUI/res/values-ru/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"\"Кадр в кадре\" – выйти"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Во весь экран"</string>
+    <string name="pip_play" msgid="674145557658227044">"Воспроизвести"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Приостановить"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Управляйте кадром в кадре, удерживая кнопку "<b>"ГЛАВНАЯ"</b></string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Управляйте режимом \"Кадр в кадре\", удерживая кнопку ГЛАВНАЯ"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"ОК"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index b485320..5a09d3e 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"තිර රුව ග්‍රහණය කරන ලදි."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"ඔබගේ තිර රුව බැලීමට ස්පර්ශ කරන්න."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"තිර රුව ග්‍රහණය කිරීමට නොහැකි විය."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"තිර රුව සුරකින අතරතුර ගැටලුවක් ඇති විය."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"සීමිත ගබඩා ඉඩ නිසා තිර රුව සුරැකිය නොහැකිය."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"තිර රූ ගැනීමට යෙදුම හෝ ඔබගේ සංවිධානය ඉඩ නොදේ."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ගොනු හුවමාරු විකල්ප"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"වැඩ ප්‍රකාරය ක්‍රියාත්මකයි."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"වැඩ ප්‍රකාරය ක්‍රියාවිරහිත කරන ලදී."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"වැඩ ප්‍රකාරය ක්‍රියාත්මක කරන ලදී."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"දීප්තිය දර්ශනය කරන්න"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G දත්ත විරාම කර ඇත"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G දත්ත විරාම කර ඇත"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings_tv.xml b/packages/SystemUI/res/values-si-rLK/strings_tv.xml
new file mode 100644
index 0000000..70884b0
--- /dev/null
+++ b/packages/SystemUI/res/values-si-rLK/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP වසන්න"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"සම්පූර්ණ තිරය"</string>
+    <string name="pip_play" msgid="674145557658227044">"ධාවනය කරන්න"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"විරාමය"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP පාලනයට "<b>"HOME"</b>" අල්ලාගන්න"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"හරි, තේරුණා"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 40daf19..edae154 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -75,6 +75,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímka obrazovky bola zaznamenaná."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Snímku obrazovky zobrazíte dotykom."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Snímku obrazovky sa nepodarilo zachytiť."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Pri ukladaní snímky obrazovky sa vyskytol problém."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snímku obrazovky nie je možné vytvoriť z dôvodu nedostatku miesta v úložisku."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Vytváranie snímok obrazovky je zakázané aplikáciou alebo vašou organizáciou."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosu súborov USB"</string>
@@ -222,6 +223,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Pracovný režim – zap."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Pracovný režim je vypnutý."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Pracovný režim je zapnutý."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Šetrič dát bol vypnutý."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Šetrič dát bol zapnutý."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Jas displeja"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Dátové prenosy 2G a 3G sú pozastavené"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Dátové prenosy 4G sú pozastavené"</string>
diff --git a/packages/SystemUI/res/values-sk/strings_tv.xml b/packages/SystemUI/res/values-sk/strings_tv.xml
new file mode 100644
index 0000000..98a67f8
--- /dev/null
+++ b/packages/SystemUI/res/values-sk/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Zavrieť režim PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Celá obrazovka"</string>
+    <string name="pip_play" msgid="674145557658227044">"Prehrať"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pozastaviť"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Režim PIP ovládajte pomocou tlačidla "<b>"PLOCHA"</b></string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Režim PIP ovládajte stlačením a podržaním tlačidla PLOCHA"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Dobre"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 756c43d..b268f18 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -75,6 +75,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Posnetek zaslona je shranjen."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Dotaknite se, če si želite ogledati posnetek zaslona."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Posnetka zaslona ni bilo mogoče shraniti."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Pri shranjevanju posnetka zaslona je prišlo do težave."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Shranjevanje posnetka zaslona ni mogoče zaradi omejenega prostora za shranjevanje."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikacija ali organizacija ne dovoljuje posnetkov zaslona."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosa datotek prek USB-ja"</string>
@@ -222,6 +223,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Način za delo vklopljen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Način za delo je izklopljen."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Način za delo je vklopljen."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Svetlost zaslona"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Prenos podatkov v omrežju 2G/3G je zaustavljen"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Prenos podatkov v omrežju 4G je zaustavljen"</string>
diff --git a/packages/SystemUI/res/values-sl/strings_tv.xml b/packages/SystemUI/res/values-sl/strings_tv.xml
new file mode 100644
index 0000000..20de9c5
--- /dev/null
+++ b/packages/SystemUI/res/values-sl/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Zapri način PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Celozaslonsko"</string>
+    <string name="pip_play" msgid="674145557658227044">"Predvajanje"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Zaustavitev"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Pridr. "<b>"HOME"</b>" za up. n. PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Pridržite gumb HOME za upravljanje načina PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Razumem"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 8b3861e..f657fb4 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Pamja e ekranit u kap."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Prek për të parë pamjen e ekranit tënd."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nuk mundi të kapte pamjen e ekranit."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"U has problem gjatë ruajtjes së pamjes së ekranit."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Pamja e ekranit nuk mund të ruhet për shkak të hapësirës ruajtëse të kufizuar."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Nxjerrja e pamjeve të ekranit nuk lejohet nga aplikacioni ose organizata jote."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opsionet e transferimit të dosjeve të USB-së"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modaliteti i punës është i aktivizuar."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modaliteti i punës është i çaktivizuar."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modaliteti i punës është i aktivizuar."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ndriçimi i ekranit"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Të dhënat 2G-3G janë ndërprerë"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Të dhënat 4G janë ndërprerë"</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings_tv.xml b/packages/SystemUI/res/values-sq-rAL/strings_tv.xml
new file mode 100644
index 0000000..481662f
--- /dev/null
+++ b/packages/SystemUI/res/values-sq-rAL/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Mbyll PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Ekrani i plotë"</string>
+    <string name="pip_play" msgid="674145557658227044">"Luaj"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pauzë"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Mbaj shtypur "<b>"HOME"</b>" për të kontrolluar PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Shtyp dhe mbaj shtypur butonin HOME për të kontrolluar PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"E kuptova"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 991e9e2..52d52e0 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -74,6 +74,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Снимак екрана је направљен."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Додирните да бисте видели снимак екрана."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Није могуће направити снимак екрана."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Дошло је до проблема при чувању снимка екрана."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Чување снимка екрана није успело због ограниченог меморијског простора."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Апликација или организација не дозвољавају прављење снимака екрана."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Опције USB преноса датотека"</string>
@@ -221,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Режим рада је укључен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Режим рада је искључен."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Режим рада је укључен."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Осветљеност екрана"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G подаци су паузирани"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G подаци су паузирани"</string>
diff --git a/packages/SystemUI/res/values-sr/strings_tv.xml b/packages/SystemUI/res/values-sr/strings_tv.xml
new file mode 100644
index 0000000..eed8f51
--- /dev/null
+++ b/packages/SystemUI/res/values-sr/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Затвори PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Цео екран"</string>
+    <string name="pip_play" msgid="674145557658227044">"Пусти"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Паузирај"</string>
+    <string name="pip_hold_home" msgid="340086535668778109"><b>"ПОЧЕТНИ ЕКРАН"</b>" конт. PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Притисните и задржите дугме ПОЧЕТНИ ЕКРАН да бисте контролисали PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Важи"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index d35fad5..1c72fa9 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Skärmdumpen har tagits."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Tryck här om du vill visa skärmdumpen."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Det gick inte att ta någon skärmdump."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Det gick inte att spara skärmdumpen."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Det går inte att spara skärmdumpen eftersom lagringsutrymmet inte räcker."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Appen eller organisationen tillåter inte att du tar skärmdumpar."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Överföringsalternativ"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Arbetsläget aktiverat."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Arbetsläget har inaktiverats."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Arbetsläget har aktiverats."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Databesparing har inaktiverats."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Databesparing har aktiverats."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Skärmens ljusstyrka"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G- och 3G-data har pausats"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data har pausats"</string>
diff --git a/packages/SystemUI/res/values-sv/strings_tv.xml b/packages/SystemUI/res/values-sv/strings_tv.xml
new file mode 100644
index 0000000..2b2c5c2
--- /dev/null
+++ b/packages/SystemUI/res/values-sv/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Stäng PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Helskärm"</string>
+    <string name="pip_play" msgid="674145557658227044">"Spela upp"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pausa"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Styr PIP med "<b>"startknappen"</b></string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Styr bild-i-bild genom att hålla ned startsideknappen"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index ddc1c0a..5fe6375 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Picha ya skrini imenaswa."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Gusa ili kuona picha yako ya skrini."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Haikuweza kunasa picha ya skrini"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Hitilafu imetokea wakati wa kuhifadhi picha ya skrini."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Haina nafasi ya kutosha kuhifadhi picha ya skrini."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Shirika au programu yako haikuruhusu upige picha za skrini."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Machaguo ya uhamisho wa faili la USB"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Hali ya kazi imewashwa."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Hali ya kazi imezimwa."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Hali ya kazi imewashwa."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Kiokoa Data kimezimwa."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Kiokoa Data kimewashwa."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ung\'aavu wa skrini"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data ya 2G-3G imesitishwa"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data ya 4G imesitishwa"</string>
diff --git a/packages/SystemUI/res/values-sw/strings_tv.xml b/packages/SystemUI/res/values-sw/strings_tv.xml
new file mode 100644
index 0000000..337c136
--- /dev/null
+++ b/packages/SystemUI/res/values-sw/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Funga PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Skrini nzima"</string>
+    <string name="pip_play" msgid="674145557658227044">"Cheza"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Sitisha"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Shikilia kitufe cha "<b>"HOME"</b>" ili udhibiti PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Bonyeza na ushikilie kitufe cha HOME ili kudhibiti PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Nimeelewa"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 122413d..a2fa3b9 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -99,6 +99,9 @@
     <!-- The top padding for the task stack. -->
     <dimen name="recents_stack_top_padding">40dp</dimen>
 
+    <!-- The size of the initial peek area at the bottom of the stack (above the nav bar). -->
+    <dimen name="recents_initial_bottom_peek_size">100dp</dimen>
+
     <!-- The side padding for the task stack. -->
     <dimen name="recents_stack_left_right_padding">64dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 66a1496..570aeae 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"ஸ்கிரீன் ஷாட் எடுக்கப்பட்டது."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"உங்கள் ஸ்க்ரீன் ஷாட்டைப் பார்க்க தொடவும்."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ஸ்க்ரீன் ஷாட்டை எடுக்க முடியவில்லை."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ஸ்க்ரீன்ஷாட்டைச் சேமிக்கும் போது, பிழை ஏற்பட்டது."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"போதுமான சேமிப்பிடம் இல்லாததால் ஸ்கிரீன்ஷாட்டைச் சேமிக்க முடியவில்லை."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"பயன்பாடு அல்லது உங்கள் நிறுவனம் ஸ்கிரீன்ஷாட்டுகளை எடுக்க அனுமதிக்கவில்லை."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB கோப்பு இடமாற்ற விருப்பங்கள்"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"பணிப் பயன்முறை இயக்கப்பட்டுள்ளது."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"பணிப் பயன்முறை முடக்கப்பட்டது."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"பணிப் பயன்முறை இயக்கப்பட்டது."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"திரை பிரகாசம்"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G டேட்டா இடைநிறுத்தப்பட்டது"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G டேட்டா இடைநிறுத்தப்பட்டது"</string>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings_tv.xml b/packages/SystemUI/res/values-ta-rIN/strings_tv.xml
new file mode 100644
index 0000000..b92af22
--- /dev/null
+++ b/packages/SystemUI/res/values-ta-rIN/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIPஐ மூடு"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"முழுத்திரை"</string>
+    <string name="pip_play" msgid="674145557658227044">"இயக்கு"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"இடைநிறுத்து"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIPஐக் கட்டுப்படுத்த, "<b>"முகப்பைப்"</b>" பிடித்திருக்கவும்"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"சரி"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index d02b353..f0e5c60 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"స్క్రీన్‌షాట్ క్యాప్చర్ చేయబడింది."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"మీ స్క్రీన్‌షాట్‌ను వీక్షించడానికి తాకండి."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"స్క్రీన్‌షాట్‌ను క్యాప్చర్ చేయడం సాధ్యపడలేదు."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"స్క్రీన్‌షాట్‌ని సేవ్ చేస్తున్నప్పుడు సమస్య సంభవించింది."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"పరిమిత నిల్వ స్థలం కారణంగా స్క్రీన్‌షాట్‌ను సేవ్ చేయడం సాధ్యపడదు."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"స్క్రీన్‌షాట్‌లు తీయడానికి అనువర్తనం లేదా మీ సంస్థ అనుమతించలేదు."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ఫైల్ బదిలీ ఎంపికలు"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"పని మోడ్ ఆన్‌లో ఉంది."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"పని మోడ్ ఆఫ్ చేయబడింది."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"పని మోడ్ ఆన్ చేయబడింది."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ప్రదర్శన ప్రకాశం"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G డేటా పాజ్ చేయబడింది"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G డేటా పాజ్ చేయబడింది"</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings_tv.xml b/packages/SystemUI/res/values-te-rIN/strings_tv.xml
new file mode 100644
index 0000000..7ce24cb
--- /dev/null
+++ b/packages/SystemUI/res/values-te-rIN/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIPని మూసివేయి"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"పూర్తి స్క్రీన్"</string>
+    <string name="pip_play" msgid="674145557658227044">"ప్లే చేయి"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"పాజ్ చేయి"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP నియం. "<b>"HOME"</b>"నొక్కిఉంచండి"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"PIPని నియంత్రించడానికి హోమ్ బటన్‌ను నొక్కి పట్టుకోండి"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"అర్థమైంది"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 9b1ea74..98029ed 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"จับภาพหน้าจอแล้ว"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"แตะเพื่อดูภาพหน้าจอของคุณ"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ไม่สามารถจับภาพหน้าจอ"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"พบปัญหาขณะกำลังบันทึกภาพหน้าจอ"</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ไม่สามารถบันทึกภาพหน้าจอเนื่องจากพื้นที่เก็บข้อมูลมีจำกัด"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"แอปหรือองค์กรของคุณไม่อนุญาตให้จับภาพหน้าจอ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"ตัวเลือกการถ่ายโอนไฟล์ USB"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"โหมดการทำงานเปิดอยู่"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"ปิดโหมดการทำงานแล้ว"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"เปิดโหมดการทำงานแล้ว"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"ความสว่างของหน้าจอ"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"หยุดการใช้ข้อมูล 2G-3G ชั่วคราวแล้ว"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"หยุดการใช้ข้อมูล 4G ชั่วคราวแล้ว"</string>
diff --git a/packages/SystemUI/res/values-th/strings_tv.xml b/packages/SystemUI/res/values-th/strings_tv.xml
new file mode 100644
index 0000000..abc1a87c
--- /dev/null
+++ b/packages/SystemUI/res/values-th/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"ปิด PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"เต็มหน้าจอ"</string>
+    <string name="pip_play" msgid="674145557658227044">"เล่น"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"หยุดชั่วคราว"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"กด "<b>"HOME"</b>" ค้างไว้เพื่อควบคุม PIP"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"รับทราบ"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index d131c84..d93fd96 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Nakuha ang screenshot."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Pindutin upang tingnan ang iyong screenshot."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Hindi makuha ang screenshot."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Nagkaroon ng problema habang sine-save ang screenshot."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Hindi ma-save ang screenshot dahil sa limitadong espasyo ng storage."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Hindi pinapayagan ng app o ng iyong organisasyon ang pagkuha ng mga screenshot."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opsyon paglipat ng USB file"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Naka-on ang work mode."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Na-off ang work mode."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Na-on ang work mode."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Liwanag ng display"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Naka-pause ang 2G-3G data"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Naka-pause ang 4G data"</string>
diff --git a/packages/SystemUI/res/values-tl/strings_tv.xml b/packages/SystemUI/res/values-tl/strings_tv.xml
new file mode 100644
index 0000000..e6aad60
--- /dev/null
+++ b/packages/SystemUI/res/values-tl/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Isara ang PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string>
+    <string name="pip_play" msgid="674145557658227044">"I-play"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"I-pause"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"I-hold ang "<b>"HOME"</b>" para makontrol ang PIP"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index fd9e14c..039a63f 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekran görüntüsü alındı."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Ekran görüntünüzü izlemek için dokunun."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Ekran görüntüsü alınamadı."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Ekran görüntüsü kaydedilirken sorun oluştu."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Depolama alanı sınırlı olduğundan ekran görüntüsü kaydedilemiyor."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Uygulama veya kuruluşunuz, ekran görüntüsü alınmasına izin vermiyor."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB dosya aktarım seçenekleri"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Çalışma modu açık."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Çalışma modu kapatıldı."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Çalışma modu açıldı."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ekran parlaklığı"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G veri kullanımı duraklatıldı"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G veri kullanımı duraklatıldı"</string>
diff --git a/packages/SystemUI/res/values-tr/strings_tv.xml b/packages/SystemUI/res/values-tr/strings_tv.xml
new file mode 100644
index 0000000..c6da011
--- /dev/null
+++ b/packages/SystemUI/res/values-tr/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"PIP\'yi kapat"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Tam ekran"</string>
+    <string name="pip_play" msgid="674145557658227044">"Oynat"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Duraklat"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"PIP\'yi kontrol etmek için "<b>"ANA EKRAN"</b>"\'ı basılı tutun"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Anladım"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index e5bf06d..e2ca5c5 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -75,6 +75,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Знімок екрана зроблено."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Торкніться, щоб переглянути знімок екрана."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Не вдалося зробити знімок екрана."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Не вдалося зберегти знімок екрана."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Не вдалося зберегти знімок екрана через обмежений обсяг пам’яті."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Додаток або ваша організація не дозволяють робити знімки екрана."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Парам.передав.файлів через USB"</string>
@@ -222,6 +223,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Робочий режим увімкнено."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Робочий режим вимкнено."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Робочий режим увімкнено."</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"Яскравість дисплея"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Передавання даних 2G–3G призупинено"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Передавання даних 4G призупинено"</string>
diff --git a/packages/SystemUI/res/values-uk/strings_tv.xml b/packages/SystemUI/res/values-uk/strings_tv.xml
new file mode 100644
index 0000000..dcb7a52
--- /dev/null
+++ b/packages/SystemUI/res/values-uk/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Закрити PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"На весь екран"</string>
+    <string name="pip_play" msgid="674145557658227044">"Відтворити"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Призупинити"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Щоб керувати PIP, утримуйте кнопку "<b>"ГОЛОВНИЙ ЕКРАН"</b></string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Щоб керувати PIP, утримуйте кнопку \"ГОЛОВНИЙ ЕКРАН\""</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 7a10732..866350c 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"اسکرین شاٹ کیپچر کیا گیا۔"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"اپنے اسکرین شاٹ دیکھنے کیلئے چھوئیں۔"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"اسکرین شاٹ کیپچر نہیں کر سکے۔"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"اسکرین شاٹ محفوظ کرتے وقت مسئلہ پیش آ گیا۔"</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"محدود اسٹوریج جگہ کی وجہ سے اسکرین شاٹس نہیں لئے جا سکتے۔"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے۔"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏USB فائل منتقل کرنیکے اختیارات"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"کام موڈ آن ہے۔"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"کام موڈ آف ہو گیا۔"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"کام موڈ آن ہو گیا۔"</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"ڈیٹا سیور آف ہو گیا۔"</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"ڈیٹا سرور آن ہو گیا۔"</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"ڈسپلے کی چمک"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"‏2G-3G ڈیٹا موقوف کر دیا گیا"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"‏4G ڈیٹا موقوف کر دیا گیا"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings_tv.xml b/packages/SystemUI/res/values-ur-rPK/strings_tv.xml
new file mode 100644
index 0000000..4216e9e
--- /dev/null
+++ b/packages/SystemUI/res/values-ur-rPK/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"‏PIP بند کریں"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"فُل اسکرین"</string>
+    <string name="pip_play" msgid="674145557658227044">"چلائیں"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"موقوف کریں"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"‏PIP کنٹرول کرنے کیلئے "<b>"ہوم"</b>" پکڑے رکھیں"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"‏PIP کنٹرول کرنے کیلئے ہوم بٹن دبائیں اور پکڑے رکھیں"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"سمجھ آ گئی"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 79729dc..fb9a9e2 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Skrinshot saqlandi."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Ko‘rish uchun bu yerga bosing."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Skrinshot saqlanmadi."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Skrinshotni saqlashda muammo yuz berdi."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Xotirada joy kamligi uchun skrinshotni saqlab bo‘lmadi."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Ilova yoki tashkilotingiz skrinshot olishni taqiqlagan."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB fayl ko‘chirish moslamalari"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Ish rejimi yoniq."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Ish rejimi o‘chirib qo‘yildi."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Ishchi rejim yoqildi."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Trafik tejash rejimi o‘chirib qo‘yildi."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Trafik tejash rejimi yoqildi."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Ekran yorqinligi"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G internet to‘xtatib qo‘yildi"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G internet to‘xtatib qo‘yildi"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml b/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml
new file mode 100644
index 0000000..d9db7d2
--- /dev/null
+++ b/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Kadr ichida kadr – chiqish"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"To‘liq ekran"</string>
+    <string name="pip_play" msgid="674145557658227044">"Ijro"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Pauza"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"“Kadr ichida kadr” rejimini boshqarish uchun "<b>"BOSHI"</b>" tugmasini bosib turing"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"“Kadr ichida kadr” rejimini boshqarish uchun BOSHIGA tugmasini bosib turing"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 074a8a0..7427bda 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Đã chụp ảnh màn hình."</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Chạm để xem ảnh chụp màn hình của bạn."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Không thể chụp ảnh màn hình."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Đã gặp phải sự cố khi đang lưu ảnh chụp màn hình."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Không thể lưu ảnh chụp màn hình do giới hạn dung lượng bộ nhớ."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Ứng dụng hoặc tổ chức của bạn không cho phép chụp ảnh màn hình."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Tùy chọn truyền tệp USB"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Chế độ làm việc bật."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Chế độ làm việc đã tắt."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Chế độ làm việc đã bật."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Đã tắt Trình tiết kiệm dữ liệu."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Đã bật Trình tiết kiệm dữ liệu."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Độ sáng màn hình"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Đã tạm dừng dữ liệu 2G-3G"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Đã tạm dừng dữ liệu 4G"</string>
diff --git a/packages/SystemUI/res/values-vi/strings_tv.xml b/packages/SystemUI/res/values-vi/strings_tv.xml
new file mode 100644
index 0000000..727dcb8
--- /dev/null
+++ b/packages/SystemUI/res/values-vi/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Đóng PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Toàn màn hình"</string>
+    <string name="pip_play" msgid="674145557658227044">"Phát"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Tạm dừng"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Giữ "<b>"HOME"</b>" để đ.khiển PIP"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index dd5ea1f..74d787f 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -73,6 +73,8 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"已抓取屏幕截图。"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"触摸可查看您的屏幕截图。"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"无法抓取屏幕截图。"</string>
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
+    <skip />
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由于存储空间有限,无法保存屏幕截图。"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"此应用或贵单位不允许进行屏幕截图。"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB文件传输选项"</string>
@@ -220,6 +222,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"工作模式开启。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"工作模式已关闭。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"工作模式已开启。"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"屏幕亮度"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G 数据网络已暂停使用"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G 数据网络已暂停使用"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
new file mode 100644
index 0000000..87b62a0
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"关闭画中画"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"全屏"</string>
+    <string name="pip_play" msgid="674145557658227044">"播放"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"暂停"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"按住"<b>"主屏幕"</b>"按钮即可控制画中画功能"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"知道了"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index bd379b7..602089e 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"已擷取螢幕畫面。"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"輕觸即可查看螢幕擷取畫面。"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"無法擷取螢幕畫面。"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"儲存螢幕擷圖時發生問題。"</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由於儲存空間有限,因此無法儲存螢幕擷取畫面。"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"此應用程式或您的機構禁止擷取螢幕畫面。"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"工作模式已開啟。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"已關閉工作模式。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"已開啟工作模式。"</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"已關閉數據節省模式。"</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"已開啟數據節省模式。"</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"顯示光暗度"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"已暫停 2G-3G 數據"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"已暫停 4G 數據"</string>
@@ -506,9 +509,9 @@
     <string name="headset" msgid="4534219457597457353">"耳機"</string>
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"已連接至耳機"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"已連接至耳機"</string>
-    <string name="data_saver" msgid="5037565123367048522">"數據節省程式"</string>
-    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"數據節省程式已開啟"</string>
-    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"數據節省程式已關閉"</string>
+    <string name="data_saver" msgid="5037565123367048522">"數據節省模式"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"數據節省模式已開啟"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"數據節省模式已關閉"</string>
     <string name="switch_bar_on" msgid="1142437840752794229">"開啟"</string>
     <string name="switch_bar_off" msgid="8803270596930432874">"關閉"</string>
     <string name="nav_bar" msgid="1993221402773877607">"導覽列"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
new file mode 100644
index 0000000..e419aa1
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"關閉 PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"全螢幕"</string>
+    <string name="pip_play" msgid="674145557658227044">"播放"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"暫停"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"按住"<b>"主按鈕"</b>"即可控制 PIP"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"知道了"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index d580b28..189f404d 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"已拍攝螢幕擷取畫面。"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"輕觸即可查看螢幕擷取畫面。"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"無法拍攝螢幕擷取畫面。"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"儲存螢幕擷圖時發生問題。"</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由於儲存空間有限,因此無法儲存螢幕擷取畫面。"</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"這個應用程式或貴機構禁止擷取螢幕畫面。"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string>
@@ -220,6 +221,10 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"工作模式已開啟。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"工作模式已關閉。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"工作模式已開啟。"</string>
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) -->
+    <skip />
+    <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) -->
+    <skip />
     <string name="accessibility_brightness" msgid="8003681285547803095">"螢幕亮度"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"已暫停 2G-3G 數據連線"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"已暫停 4G 數據連線"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
new file mode 100644
index 0000000..94a83b9
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"關閉子母畫面"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"全螢幕"</string>
+    <string name="pip_play" msgid="674145557658227044">"播放"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"暫停"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"按住「主畫面」"<b></b>"按鈕即可控制子母畫面"</string>
+    <!-- no translation found for pip_onboarding_description (2882896641362814195) -->
+    <skip />
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"我知道了"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 9382b26..60c4479 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -73,6 +73,7 @@
     <string name="screenshot_saved_title" msgid="6461865960961414961">"Umfanekiso weskrini uqoshiwe"</string>
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Thinta ukubona imifanekiso yakho yeskrini"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Yehlulekile ukulondoloza umfanekiso weskrini."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Inkinga ivelile ngenkathi ilondoloza isithombe sikrini."</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ayikwazi ukulondoloza isithombe-skrini ngenxa yesikhala sesitoreji esikhawulelwe."</string>
     <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Ukuthatha izithombe-skrini akuvunyelwe uhlelo lokusebenza noma inhlangano yakho."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Okukhethwa kokudluliswa kwefayela ye-USB"</string>
@@ -220,6 +221,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Imodi yomsebenzi ivuliwe."</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Imodi yomsebenzi ivaliwe."</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Imodi yomsebenzi ivuliwe."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Iseva yedatha ivaliwe."</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Iseva yedatha ivuliwe."</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"Bonisa ukukhanya"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G idatha imisiwe"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G idatha imisiwe"</string>
diff --git a/packages/SystemUI/res/values-zu/strings_tv.xml b/packages/SystemUI/res/values-zu/strings_tv.xml
new file mode 100644
index 0000000..b010556
--- /dev/null
+++ b/packages/SystemUI/res/values-zu/strings_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2016, 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:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="pip_close" msgid="3480680679023423574">"Vala i-PIP"</string>
+    <string name="pip_fullscreen" msgid="8604643018538487816">"Iskrini esigcwele"</string>
+    <string name="pip_play" msgid="674145557658227044">"Dlala"</string>
+    <string name="pip_pause" msgid="8412075640017218862">"Misa isikhashana"</string>
+    <string name="pip_hold_home" msgid="340086535668778109">"Bamba "<b>"IKHAYA"</b>" ukuze ulawule i-PIP"</string>
+    <string name="pip_onboarding_description" msgid="2882896641362814195">"Cindezela futhi ubambe inkinobho EKHAYA ukuze ulawule i-PIP"</string>
+    <string name="pip_onboarding_button" msgid="3957426748484904611">"Ngiyezwa"</string>
+</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 30acc72..d65ab04 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -165,4 +165,7 @@
     <!-- Keyboard shortcuts colors -->
     <color name="ksh_system_group_color">#ff00bcd4</color>
     <color name="ksh_application_group_color">#fff44336</color>
+
+    <!-- Background color of edit overflow -->
+    <color name="qs_edit_overflow_bg">#455A64</color>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 3d5c606..6a9f456 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -58,19 +58,19 @@
     <item name="status_bar_icon_scale_factor" format="float" type="dimen">1.0</item>
 
     <!-- Height of a small notification in the status bar-->
-    <dimen name="notification_min_height">86dp</dimen>
+    <dimen name="notification_min_height">92dp</dimen>
 
     <!-- Height of a small notification in the status bar which was used before android N -->
     <dimen name="notification_min_height_legacy">64dp</dimen>
 
     <!-- Height of a large notification in the status bar -->
-    <dimen name="notification_max_height">276dp</dimen>
+    <dimen name="notification_max_height">284dp</dimen>
 
     <!-- Height of a heads up notification in the status bar for legacy custom views -->
     <dimen name="notification_max_heads_up_height_legacy">128dp</dimen>
 
     <!-- Height of a heads up notification in the status bar -->
-    <dimen name="notification_max_heads_up_height">141dp</dimen>
+    <dimen name="notification_max_heads_up_height">148dp</dimen>
 
     <!-- Height of a the summary ("more card") notification on keyguard. -->
     <dimen name="notification_summary_height">44dp</dimen>
@@ -178,7 +178,7 @@
     <dimen name="qs_date_alarm_anim_translation">22dp</dimen>
     <dimen name="qs_date_collapsed_text_size">14sp</dimen>
     <dimen name="qs_date_text_size">16sp</dimen>
-    <dimen name="qs_header_gear_translation">150dp</dimen>
+    <dimen name="qs_header_gear_translation">16dp</dimen>
     <dimen name="qs_page_indicator_size">12dp</dimen>
     <dimen name="qs_tile_icon_size">24dp</dimen>
     <dimen name="qs_tile_text_size">12sp</dimen>
@@ -295,6 +295,9 @@
     <!-- The size of the initial peek area at the top of the stack (below the status bar). -->
     <dimen name="recents_initial_top_peek_size">8dp</dimen>
 
+    <!-- The size of the initial peek area at the bottom of the stack (above the nav bar). -->
+    <dimen name="recents_initial_bottom_peek_size">100dp</dimen>
+
     <!-- The size of the peek area at the top of the stack (below the status bar). -->
     <dimen name="recents_layout_focused_top_peek_size">@dimen/recents_history_button_height</dimen>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 1f239c3..5295ccb 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -185,7 +185,9 @@
     <string name="screenshot_saved_text">Touch to view your screenshot.</string>
     <!-- Notification title displayed when we fail to take a screenshot. [CHAR LIMIT=50] -->
     <string name="screenshot_failed_title">Couldn\'t capture screenshot.</string>
-    <!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] -->
+    <!-- Notification text displayed when we fail to save a screenshot for unknown reasons. [CHAR LIMIT=100] -->
+    <string name="screenshot_failed_to_save_unknown_text">Problem encountered while saving screenshot.</string>
+    <!-- Notification text displayed when we fail to save a screenshot. [CHAR LIMIT=100] -->
     <string name="screenshot_failed_to_save_text">Can\'t save screenshot due to limited storage space.</string>
     <!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] -->
     <string name="screenshot_failed_to_capture_text">Taking screenshots is not allowed by the app or your organization.</string>
@@ -523,6 +525,10 @@
     <string name="accessibility_quick_settings_work_mode_changed_off">Work mode turned off.</string>
     <!-- Announcement made when the work mode changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_work_mode_changed_on">Work mode turned on.</string>
+    <!-- Announcement made when the Data Saver changes to off (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_data_saver_changed_off">Data Saver turned off.</string>
+    <!-- Announcement made when the Data Saver changes to on (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_quick_settings_data_saver_changed_on">Data Saver turned on.</string>
 
     <!-- Content description of the display brightness slider (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_brightness">Display brightness</string>
@@ -709,7 +715,9 @@
     <string name="quick_settings_work_mode_label">Work mode</string>
 
     <!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
-    <string name="recents_empty_message">Your recent screens appear here</string>
+    <string name="recents_empty_message">No recent items</string>
+    <!-- Recents: The empty recents string after dismissing all tasks. [CHAR LIMIT=NONE] -->
+    <string name="recents_empty_message_dismissed_all">You\'ve cleared everything</string>
     <!-- Recents: The info panel app info button string. [CHAR LIMIT=NONE] -->
     <string name="recents_app_info_button_label">Application Info</string>
     <!-- Recents: The screen pinning button. [CHAR LIMIT=NONE] -->
@@ -1178,11 +1186,6 @@
     <!-- Option to use new paging layout in quick settings [CHAR LIMIT=60] -->
     <string name="qs_paging" translatable="false">Use the new Quick Settings</string>
 
-    <!-- Disables fast-toggling recents via the recents button. DO NOT TRANSLATE -->
-    <string name="overview_disable_fast_toggle_via_button">Disable fast toggle</string>
-    <!-- Description for the toggle for fast-toggling recents via the recents button. DO NOT TRANSLATE -->
-    <string name="overview_disable_fast_toggle_via_button_desc">Disable launch timeout while paging</string>
-
     <!-- Toggle to enable the gesture to enter split-screen by swiping up from the Overview button. [CHAR LIMIT=60]-->
     <string name="overview_nav_bar_gesture">Enable split-screen swipe-up gesture</string>
     <!-- Description for the toggle to enable the gesture to enter split-screen by swiping up from the Overview button. [CHAR LIMIT=NONE]-->
@@ -1429,6 +1432,9 @@
     <!-- Label for area where tiles can be dragged out of [CHAR LIMIT=60] -->
     <string name="drag_to_add_tiles">Drag to add tiles</string>
 
+    <!-- Label for area where tiles can be dragged in to [CHAR LIMIT=60] -->
+    <string name="drag_to_remove_tiles">Drag here to remove</string>
+
     <!-- Button to edit the tile ordering of quick settings [CHAR LIMIT=60] -->
     <string name="qs_edit">Edit</string>
 
diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml
index c7fb0ec..0e1fe8f 100644
--- a/packages/SystemUI/res/values/strings_tv.xml
+++ b/packages/SystemUI/res/values/strings_tv.xml
@@ -17,26 +17,24 @@
  */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Picture-in-Picture menu -->
+    <!-- Picture-in-Picture (PIP) menu -->
     <eat-comment />
-    <!-- Button to close PIP on PIP UI -->
-    <string name="pip_close" translatable="false">Close PIP</string>
-    <!-- Button to move PIP screen to the fullscreen on PIP UI -->
-    <string name="pip_fullscreen" translatable="false">Full screen</string>
-    <!-- Button to play the current media on PIP UI -->
-    <string name="pip_play" translatable="false">Play</string>
-    <!-- Button to pause the current media on PIP UI -->
-    <string name="pip_pause" translatable="false">Pause</string>
-    <!-- Button to close PIP overlay menu on PIP UI -->
-    <string name="pip_cancel" translatable="false">Cancel</string>
-    <!-- Overlay text on PIP -->
-    <string name="pip_hold_home" translatable="false">Hold <b>HOME</b> to control PIP</string>
-    <!-- Picture-in-Picture onboarding screen -->
+    <!-- Button to close picture-in-picture (PIP) in PIP menu [CHAR LIMIT=16] -->
+    <string name="pip_close">Close PIP</string>
+    <!-- Button to move picture-in-picture (PIP) screen to the fullscreen in PIP menu [CHAR LIMIT=16] -->
+    <string name="pip_fullscreen">Full screen</string>
+    <!-- Button to play the current media on picture-in-picture (PIP) [CHAR LIMIT=16] -->
+    <string name="pip_play">Play</string>
+    <!-- Button to pause the current media on picture-in-picture (PIP) [CHAR LIMIT=16] -->
+    <string name="pip_pause">Pause</string>
+    <!-- Overlay text on picture-in-picture (PIP) to indicate that longpress HOME key to control PIP [CHAR LIMIT=52] -->
+    <string name="pip_hold_home">Hold <b>HOME</b> to control PIP</string>
+    <!-- Picture-in-Picture (PIP) onboarding screen -->
     <eat-comment />
-    <!-- Description for onboarding screen. -->
-    <string name="pip_onboarding_description" translatable="false">Press and hold the HOME\nbutton to close or control it</string>
-    <!-- Button to close onboarding screen. -->
-    <string name="pip_onboarding_button" translatable="false">Got it</string>
+    <!-- Description for picture-in-picture (PIP) onboarding screen to indicate that longpress HOME key to control PIP. [CHAR LIMIT=NONE] -->
+    <string name="pip_onboarding_description">Press and hold the HOME button to control PIP</string>
+    <!-- Button to close picture-in-picture (PIP) onboarding screen. -->
+    <string name="pip_onboarding_button">Got it</string>
     <!-- Font for Recents -->
     <!-- DO NOT TRANSLATE -->
     <string name="font_roboto_regular" translatable="false">sans-serif</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 89890d6..2660926 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -339,4 +339,8 @@
         <item name="android:colorAccent">@color/switch_accent_color</item>
     </style>
 
+    <style name="edit_theme" parent="@android:style/Theme.Material">
+        <item name="android:colorBackground">@color/qs_edit_overflow_bg</item>
+    </style>
+
 </resources>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index ddc03a3..a130cf9 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -138,11 +138,6 @@
         android:title="@string/other" >
 
         <com.android.systemui.tuner.TunerSwitch
-            android:key="overview_disable_fast_toggle_via_button"
-            android:title="@string/overview_disable_fast_toggle_via_button"
-            android:summary="@string/overview_disable_fast_toggle_via_button_desc" />
-
-        <com.android.systemui.tuner.TunerSwitch
             android:key="overview_nav_bar_gesture"
             android:title="@string/overview_nav_bar_gesture"
             android:summary="@string/overview_nav_bar_gesture_desc" />
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 051921a..358674c 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -78,6 +78,7 @@
     private float mOldHeight;
     private float mNaturalHeight;
     private float mInitialTouchFocusY;
+    private float mInitialTouchX;
     private float mInitialTouchY;
     private float mInitialTouchSpan;
     private float mLastFocusY;
@@ -291,7 +292,8 @@
                 }
                 if (mWatchingForPull) {
                     final float yDiff = ev.getRawY() - mInitialTouchY;
-                    if (yDiff > mTouchSlop) {
+                    final float xDiff = ev.getRawX() - mInitialTouchX;
+                    if (yDiff > mTouchSlop && yDiff > Math.abs(xDiff)) {
                         if (DEBUG) Log.v(TAG, "got venetian gesture (dy=" + yDiff + "px)");
                         mWatchingForPull = false;
                         if (mResizedView != null && !isFullyExpanded(mResizedView)) {
@@ -316,6 +318,7 @@
                     mWatchingForPull = false;
                 }
                 mInitialTouchY = ev.getY();
+                mInitialTouchX = ev.getX();
                 break;
 
             case MotionEvent.ACTION_CANCEL:
@@ -409,12 +412,14 @@
                 mWatchingForPull = mScrollAdapter != null &&
                         isInside(mScrollAdapter.getHostView(), x, y);
                 mResizedView = findView(x, y);
+                mInitialTouchX = ev.getX();
                 mInitialTouchY = ev.getY();
                 break;
             case MotionEvent.ACTION_MOVE: {
                 if (mWatchingForPull) {
                     final float yDiff = ev.getRawY() - mInitialTouchY;
-                    if (yDiff > mTouchSlop) {
+                    final float xDiff = ev.getRawX() - mInitialTouchX;
+                    if (yDiff > mTouchSlop && yDiff > Math.abs(xDiff)) {
                         if (DEBUG) Log.v(TAG, "got venetian gesture (dy=" + yDiff + "px)");
                         mWatchingForPull = false;
                         if (mResizedView != null && !isFullyExpanded(mResizedView)) {
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index f6dcc11..81ba23f 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -32,6 +32,7 @@
 import android.view.accessibility.AccessibilityEvent;
 
 import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.statusbar.FlingAnimationUtils;
 
 public class SwipeHelper implements Gefingerpoken {
     static final String TAG = "com.android.systemui.SwipeHelper";
@@ -58,6 +59,7 @@
     private float mMinSwipeProgress = 0f;
     private float mMaxSwipeProgress = 1f;
 
+    private FlingAnimationUtils mFlingAnimationUtils;
     private float mPagingTouchSlop;
     private Callback mCallback;
     private Handler mHandler;
@@ -95,6 +97,8 @@
         mFalsingThreshold = context.getResources().getDimensionPixelSize(
                 R.dimen.swipe_helper_falsing_threshold);
         mFalsingManager = FalsingManager.getInstance(context);
+        mFlingAnimationUtils = new FlingAnimationUtils(context,
+                MAX_ESCAPE_ANIMATION_DURATION / 1000f /* maxLengthSeconds */);
     }
 
     public void setLongPressListener(LongPressListener listener) {
@@ -320,7 +324,8 @@
      * @param velocity The desired pixels/second speed at which the view should move
      */
     public void dismissChild(final View view, float velocity) {
-        dismissChild(view, velocity, null, 0, false, 0);
+        dismissChild(view, velocity, null /* endAction */, 0 /* delay */,
+                velocity == 0 /* useAccelerateInterpolator */, 0 /* fixedDuration */);
     }
 
     /**
@@ -377,10 +382,11 @@
         }
         if (useAccelerateInterpolator) {
             anim.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+            anim.setDuration(duration);
         } else {
-            anim.setInterpolator(Interpolators.LINEAR);
+            mFlingAnimationUtils.applyDismissing(anim, getTranslation(animView),
+                    newPos, velocity, getSize(animView));
         }
-        anim.setDuration(duration);
         if (delay > 0) {
             anim.setStartDelay(delay);
         }
@@ -511,35 +517,16 @@
                 break;
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
-                if (mCurrView != null) {
-                    float maxVelocity = MAX_DISMISS_VELOCITY * mDensityScale;
-                    mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, maxVelocity);
-                    float escapeVelocity = SWIPE_ESCAPE_VELOCITY * mDensityScale;
-                    float velocity = getVelocity(mVelocityTracker);
-                    float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker);
+                if (mCurrView == null) {
+                    break;
+                }
+                mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, getMaxVelocity());
+                float velocity = getVelocity(mVelocityTracker);
 
-                    float translation = getTranslation(mCurrView);
-                    // Decide whether to dismiss the current view
-                    boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH &&
-                            Math.abs(translation) > 0.4 * getSize(mCurrView);
-                    boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) &&
-                            (Math.abs(velocity) > Math.abs(perpendicularVelocity)) &&
-                            (velocity > 0) == (translation > 0);
-                    boolean falsingDetected = mCallback.isAntiFalsingNeeded();
-
-                    if (mFalsingManager.isClassiferEnabled()) {
-                        falsingDetected = falsingDetected && mFalsingManager.isFalseTouch();
-                    } else {
-                        falsingDetected = falsingDetected && !mTouchAboveFalsingThreshold;
-                    }
-
-                    boolean dismissChild = mCallback.canChildBeDismissed(mCurrView)
-                            && !falsingDetected && (childSwipedFastEnough || childSwipedFarEnough)
-                            && ev.getActionMasked() == MotionEvent.ACTION_UP;
-
-                    if (dismissChild) {
+                if (!handleUpEvent(ev, mCurrView, velocity, getTranslation(mCurrView))) {
+                    if (isDismissGesture(ev)) {
                         // flingadingy
-                        dismissChild(mCurrView, childSwipedFastEnough ? velocity : 0f);
+                        dismissChild(mCurrView, swipedFastEnough() ? velocity : 0f);
                     } else {
                         // snappity
                         mCallback.onDragCancelled(mCurrView);
@@ -556,6 +543,46 @@
         return (int) (mFalsingThreshold * factor);
     }
 
+    private float getMaxVelocity() {
+        return MAX_DISMISS_VELOCITY * mDensityScale;
+    }
+
+    protected float getEscapeVelocity() {
+        return SWIPE_ESCAPE_VELOCITY * mDensityScale;
+    }
+
+    protected boolean swipedFarEnough() {
+        float translation = getTranslation(mCurrView);
+        return DISMISS_IF_SWIPED_FAR_ENOUGH && Math.abs(translation) > 0.4 * getSize(mCurrView);
+    }
+
+    protected boolean isDismissGesture(MotionEvent ev) {
+        boolean falsingDetected = mCallback.isAntiFalsingNeeded();
+        if (mFalsingManager.isClassiferEnabled()) {
+            falsingDetected = falsingDetected && mFalsingManager.isFalseTouch();
+        } else {
+            falsingDetected = falsingDetected && !mTouchAboveFalsingThreshold;
+        }
+        return !falsingDetected && (swipedFastEnough() || swipedFarEnough())
+                && ev.getActionMasked() == MotionEvent.ACTION_UP
+                && mCallback.canChildBeDismissed(mCurrView);
+    }
+
+    protected boolean swipedFastEnough() {
+        float velocity = getVelocity(mVelocityTracker);
+        float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker);
+        float translation = getTranslation(mCurrView);
+        boolean ret = (Math.abs(velocity) > getEscapeVelocity()) &&
+                (Math.abs(velocity) > Math.abs(perpendicularVelocity)) &&
+                (velocity > 0) == (translation > 0);
+        return ret;
+    }
+
+    protected boolean handleUpEvent(MotionEvent ev, View animView, float velocity,
+            float translation) {
+        return false;
+    }
+
     public interface Callback {
         View getChildAtPosition(MotionEvent ev);
 
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 937f7d3..0d822cb 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -166,7 +166,9 @@
      */
     public boolean isFalseTouch() {
         if (FalsingLog.ENABLED) {
-            if (!mSessionActive) {
+            // We're getting some false wtfs from touches that happen after the device went
+            // to sleep. Only report missing sessions that happen when the device is interactive.
+            if (!mSessionActive && mContext.getSystemService(PowerManager.class).isInteractive()) {
                 FalsingLog.wtf("isFalseTouch", new StringBuilder()
                         .append("Session is not active, yet there's a query for a false touch.")
                         .append(" enabled=").append(isEnabled() ? 1 : 0)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 312d3c5..02b860c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -811,7 +811,7 @@
         intent.putExtra("seq", mDelayedShowingSequence);
         PendingIntent sender = PendingIntent.getBroadcast(mContext,
                 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
-        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender);
+        mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender);
         if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = "
                          + mDelayedShowingSequence);
         doKeyguardLaterForChildProfilesLocked();
@@ -828,7 +828,8 @@
                 lockIntent.putExtra(Intent.EXTRA_USER_ID, info.id);
                 PendingIntent lockSender = PendingIntent.getBroadcast(
                         mContext, 0, lockIntent, PendingIntent.FLAG_CANCEL_CURRENT);
-                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, userWhen, lockSender);
+                mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                        userWhen, lockSender);
             }
         }
     }
@@ -1542,13 +1543,22 @@
             try {
                 mStatusBarKeyguardViewManager.keyguardGoingAway();
 
+                int flags = 0;
+                if (mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock()
+                        || mWakeAndUnlocking) {
+                    flags |= WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
+                }
+                if (mStatusBarKeyguardViewManager.isGoingToNotificationShade()) {
+                    flags |= WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
+                }
+                if (mStatusBarKeyguardViewManager.isUnlockWithWallpaper()) {
+                    flags |= WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
+                }
+
                 // Don't actually hide the Keyguard at the moment, wait for window
                 // manager until it tells us it's safe to do so with
                 // startKeyguardExitAnimation.
-                ActivityManagerNative.getDefault().keyguardGoingAway(
-                        mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock()
-                                || mWakeAndUnlocking,
-                        mStatusBarKeyguardViewManager.isGoingToNotificationShade());
+                ActivityManagerNative.getDefault().keyguardGoingAway(flags);
             } catch (RemoteException e) {
                 Log.e(TAG, "Error while calling WindowManager", e);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PathInterpolatorBuilder.java b/packages/SystemUI/src/com/android/systemui/qs/PathInterpolatorBuilder.java
new file mode 100644
index 0000000..b8cb92a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/PathInterpolatorBuilder.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.qs;
+
+import android.graphics.Path;
+import android.view.animation.BaseInterpolator;
+import android.view.animation.Interpolator;
+
+public class PathInterpolatorBuilder {
+
+    // This governs how accurate the approximation of the Path is.
+    private static final float PRECISION = 0.002f;
+
+    private float[] mX; // x coordinates in the line
+    private float[] mY; // y coordinates in the line
+    private float[] mDist; // Cumulative percentage length of the line
+
+    public PathInterpolatorBuilder(Path path) {
+        initPath(path);
+    }
+
+    public PathInterpolatorBuilder(float controlX, float controlY) {
+        initQuad(controlX, controlY);
+    }
+
+    public PathInterpolatorBuilder(float controlX1, float controlY1, float controlX2,
+            float controlY2) {
+        initCubic(controlX1, controlY1, controlX2, controlY2);
+    }
+
+    private void initQuad(float controlX, float controlY) {
+        Path path = new Path();
+        path.moveTo(0, 0);
+        path.quadTo(controlX, controlY, 1f, 1f);
+        initPath(path);
+    }
+
+    private void initCubic(float x1, float y1, float x2, float y2) {
+        Path path = new Path();
+        path.moveTo(0, 0);
+        path.cubicTo(x1, y1, x2, y2, 1f, 1f);
+        initPath(path);
+    }
+
+    private void initPath(Path path) {
+        float[] pointComponents = path.approximate(PRECISION);
+
+        int numPoints = pointComponents.length / 3;
+        if (pointComponents[1] != 0 || pointComponents[2] != 0
+                || pointComponents[pointComponents.length - 2] != 1
+                || pointComponents[pointComponents.length - 1] != 1) {
+            throw new IllegalArgumentException("The Path must start at (0,0) and end at (1,1)");
+        }
+
+        mX = new float[numPoints];
+        mY = new float[numPoints];
+        mDist = new float[numPoints];
+        float prevX = 0;
+        float prevFraction = 0;
+        int componentIndex = 0;
+        for (int i = 0; i < numPoints; i++) {
+            float fraction = pointComponents[componentIndex++];
+            float x = pointComponents[componentIndex++];
+            float y = pointComponents[componentIndex++];
+            if (fraction == prevFraction && x != prevX) {
+                throw new IllegalArgumentException(
+                        "The Path cannot have discontinuity in the X axis.");
+            }
+            if (x < prevX) {
+                throw new IllegalArgumentException("The Path cannot loop back on itself.");
+            }
+            mX[i] = x;
+            mY[i] = y;
+            if (i > 0) {
+                float dx = mX[i] - mX[i - 1];
+                float dy = mY[i] - mY[i - 1];
+                float dist = (float) Math.sqrt(dx * dx + dy * dy);
+                mDist[i] = mDist[i - 1] + dist;
+            }
+            prevX = x;
+            prevFraction = fraction;
+        }
+        // Scale down dist to 0-1.
+        float max = mDist[mDist.length - 1];
+        for (int i = 0; i < numPoints; i++) {
+            mDist[i] /= max;
+        }
+    }
+
+    public Interpolator getXInterpolator() {
+        return new PathInterpolator(mDist, mX);
+    }
+
+    public Interpolator getYInterpolator() {
+        return new PathInterpolator(mDist, mY);
+    }
+
+    private static class PathInterpolator extends BaseInterpolator {
+        private final float[] mX; // x coordinates in the line
+        private final float[] mY; // y coordinates in the line
+
+        private PathInterpolator(float[] xs, float[] ys) {
+            mX = xs;
+            mY = ys;
+        }
+
+        @Override
+        public float getInterpolation(float t) {
+            if (t <= 0) {
+                return 0;
+            } else if (t >= 1) {
+                return 1;
+            }
+            // Do a binary search for the correct x to interpolate between.
+            int startIndex = 0;
+            int endIndex = mX.length - 1;
+
+            while (endIndex - startIndex > 1) {
+                int midIndex = (startIndex + endIndex) / 2;
+                if (t < mX[midIndex]) {
+                    endIndex = midIndex;
+                } else {
+                    startIndex = midIndex;
+                }
+            }
+
+            float xRange = mX[endIndex] - mX[startIndex];
+            if (xRange == 0) {
+                return mY[startIndex];
+            }
+
+            float tInRange = t - mX[startIndex];
+            float fraction = tInRange / xRange;
+
+            float startY = mY[startIndex];
+            float endY = mY[endIndex];
+            return startY + (fraction * (endY - startY));
+        }
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 3d455993..815c679 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -41,6 +41,7 @@
     private static final String MOVE_FULL_ROWS = "sysui_qs_move_whole_rows";
 
     public static final float EXPANDED_TILE_DELAY = .7f;
+    private static final float LAST_ROW_EXPANDED_DELAY = .84f;
 
     private final ArrayList<View> mAllViews = new ArrayList<>();
     private final ArrayList<View> mTopFiveQs = new ArrayList<>();
@@ -53,8 +54,10 @@
     private boolean mOnFirstPage = true;
     private TouchAnimator mFirstPageAnimator;
     private TouchAnimator mFirstPageDelayedAnimator;
-    private TouchAnimator mTranslationAnimator;
+    private TouchAnimator mTranslationXAnimator;
+    private TouchAnimator mTranslationYAnimator;
     private TouchAnimator mNonfirstPageAnimator;
+    private TouchAnimator mLastRowAnimator;
 
     private boolean mOnKeyguard;
 
@@ -86,6 +89,7 @@
 
     public void setHost(QSTileHost qsh) {
         qsh.addCallback(this);
+        updateAnimators();
     }
 
     @Override
@@ -128,20 +132,21 @@
         TouchAnimator.Builder firstPageBuilder = new Builder();
         TouchAnimator.Builder translationXBuilder = new Builder();
         TouchAnimator.Builder translationYBuilder = new Builder();
-        TouchAnimator.Builder firstPageDelayedBuilder = new Builder();
+        TouchAnimator.Builder lastRowBuilder = new Builder();
+
+        if (mQsPanel.getHost() == null) return;
         Collection<QSTile<?>> tiles = mQsPanel.getHost().getTiles();
         int count = 0;
         int[] loc1 = new int[2];
         int[] loc2 = new int[2];
         int lastYDiff = 0;
-        firstPageDelayedBuilder.setStartDelay(EXPANDED_TILE_DELAY);
-        firstPageBuilder.setListener(this);
-        // Fade in the tiles/labels as we reach the final position.
-        firstPageDelayedBuilder.addFloat(mQsPanel.getTileLayout(), "alpha", 0, 1);
+
         clearAnimationState();
         mAllViews.clear();
         mTopFiveQs.clear();
+
         mAllViews.add((View) mQsPanel.getTileLayout());
+
         for (QSTile<?> tile : tiles) {
             QSTileBaseView tileView = mQsPanel.getTileView(tile);
             final TextView label = ((QSTileView) tileView).getLabel();
@@ -170,32 +175,42 @@
 
                 mTopFiveQs.add(tileIcon);
                 mAllViews.add(tileIcon);
-                mAllViews.add(label);
                 mAllViews.add(quickTileView);
             } else if (mFullRows && isIconInAnimatedRow(count)) {
                 firstPageBuilder.addFloat(tileView, "translationY", mQsPanel.getHeight(), 0);
                 translationYBuilder.addFloat(label, "translationY", -lastYDiff, 0);
                 translationYBuilder.addFloat(tileIcon, "translationY", -lastYDiff, 0);
                 mAllViews.add(tileIcon);
-                mAllViews.add(label);
+            } else {
+                lastRowBuilder.addFloat(tileView, "alpha", 0, 1);
             }
             mAllViews.add(tileView);
             mAllViews.add(label);
             count++;
         }
         if (mAllowFancy) {
-            mFirstPageAnimator = firstPageBuilder.build();
-            mFirstPageDelayedAnimator = firstPageDelayedBuilder.build();
+            mFirstPageAnimator = firstPageBuilder
+                    .setListener(this)
+                    .build();
+            // Fade in the tiles/labels as we reach the final position.
+            mFirstPageDelayedAnimator = new TouchAnimator.Builder()
+                    .setStartDelay(EXPANDED_TILE_DELAY)
+                    .addFloat(mQsPanel.getTileLayout(), "alpha", 0, 1).build();
+            mLastRowAnimator = lastRowBuilder
+                    .setStartDelay(LAST_ROW_EXPANDED_DELAY)
+                    .build();
             Path path = new Path();
             path.moveTo(0, 0);
             path.cubicTo(0, 0, 0, 1, 1, 1);
-            mTranslationAnimator = new TouchAnimator.Builder()
-                    .addPath(translationXBuilder.build(), translationYBuilder.build(),
-                            "position", "position", path)
-                    .build();
+            PathInterpolatorBuilder interpolatorBuilder = new PathInterpolatorBuilder(0, 0, 0, 1);
+            translationXBuilder.setInterpolator(interpolatorBuilder.getXInterpolator());
+            translationYBuilder.setInterpolator(interpolatorBuilder.getYInterpolator());
+            mTranslationXAnimator = translationXBuilder.build();
+            mTranslationYAnimator = translationYBuilder.build();
         }
         mNonfirstPageAnimator = new TouchAnimator.Builder()
                 .addFloat(mQuickQsPanel, "alpha", 1, 0)
+                .setListener(mNonFirstPageListener)
                 .setEndDelay(.5f)
                 .build();
     }
@@ -230,7 +245,9 @@
             mQuickQsPanel.setAlpha(1);
             mFirstPageAnimator.setPosition(position);
             mFirstPageDelayedAnimator.setPosition(position);
-            mTranslationAnimator.setPosition(position);
+            mTranslationXAnimator.setPosition(position);
+            mTranslationYAnimator.setPosition(position);
+            mLastRowAnimator.setPosition(position);
         } else {
             mNonfirstPageAnimator.setPosition(position);
         }
@@ -264,7 +281,7 @@
     private void clearAnimationState() {
         final int N = mAllViews.size();
         mQuickQsPanel.setAlpha(0);
-        mQuickQsPanel.setVisibility(View.VISIBLE);
+        mQuickQsPanel.setVisibility(View.INVISIBLE);
         for (int i = 0; i < N; i++) {
             View v = mAllViews.get(i);
             v.setAlpha(1);
@@ -290,6 +307,14 @@
         mQsPanel.post(mUpdateAnimators);
     }
 
+    private final TouchAnimator.Listener mNonFirstPageListener =
+            new TouchAnimator.ListenerAdapter() {
+                @Override
+                public void onAnimationStarted() {
+                    mQuickQsPanel.setVisibility(View.VISIBLE);
+                }
+            };
+
     private Runnable mUpdateAnimators = new Runnable() {
         @Override
         public void run() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index d0e034b..ab90179 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -26,6 +26,8 @@
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile.SignalState;
 import com.android.systemui.qs.QSTile.State;
+import com.android.systemui.qs.customize.QSCustomizer;
+import com.android.systemui.statusbar.phone.QSTileHost;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 
@@ -95,9 +97,17 @@
         return new QSTileBaseView(mContext, tile.createTileView(mContext));
     }
 
+    @Override
+    public void setHost(QSTileHost host, QSCustomizer customizer) {
+        super.setHost(host, customizer);
+        setTiles(mHost.getTiles());
+    }
+
     public void setMaxTiles(int maxTiles) {
         mMaxTiles = maxTiles;
-        setTiles(mHost.getTiles());
+        if (mHost != null) {
+            setTiles(mHost.getTiles());
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
index db17245..37f2528 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java
@@ -14,11 +14,8 @@
 
 package com.android.systemui.qs;
 
-import android.graphics.Path;
-import android.graphics.PathMeasure;
 import android.util.FloatProperty;
 import android.util.MathUtils;
-import android.util.Pair;
 import android.util.Property;
 import android.view.View;
 import android.view.animation.Interpolator;
@@ -141,19 +138,6 @@
             return this;
         }
 
-        public Builder addPath(Object target, String xProp, String yProp,
-                Path path) {
-            return addPath(target, target, xProp, yProp, path);
-        }
-
-        public Builder addPath(Object xTarget, Object yTarget, String xProp, String yProp,
-                Path path) {
-            add(new Pair<>(xTarget, yTarget),
-                    KeyframeSet.ofPath(getProperty(xTarget, xProp, float.class),
-                    getProperty(yTarget, yProp, float.class), path));
-            return this;
-        }
-
         private void add(Object target, KeyframeSet keyframeSet) {
             mTargets.add(target);
             mValues.add(keyframeSet);
@@ -241,10 +225,6 @@
         public static KeyframeSet ofFloat(Property property, float... values) {
             return new FloatKeyframeSet((Property<?, Float>) property, values);
         }
-
-        public static KeyframeSet ofPath(Property xProp, Property yProp, Path path) {
-            return new PathKeyframeSet<>(xProp, yProp, path);
-        }
     }
 
     private static class FloatKeyframeSet<T> extends KeyframeSet {
@@ -282,31 +262,4 @@
             mProperty.set((T) target, (int) (firstFloat + (secondFloat - firstFloat) * amount));
         }
     }
-
-    private static class PathKeyframeSet<T> extends KeyframeSet {
-        private final Property<T, Float> mXProp;
-        private final Property<T, Float> mYProp;
-        private final Path mPath;
-        private final PathMeasure mPathMeasure;
-        private final float mLength;
-        private final float[] mPos;
-
-        public PathKeyframeSet(Property<T, Float> xProp, Property<T, Float> yProp, Path path) {
-            super(2);
-            mXProp = xProp;
-            mYProp = yProp;
-            mPath = path;
-            mPathMeasure = new PathMeasure(mPath, false);
-            mLength = mPathMeasure.getLength();
-            mPos = new float[2];
-        }
-
-        @Override
-        protected void interpolate(int index, float amount, Object target) {
-            Pair<Object, Object> targets = (Pair<Object, Object>) target;
-            mPathMeasure.getPosTan(amount * mLength, mPos, null);
-            mXProp.set((T) targets.first, mPos[0]);
-            mYProp.set((T) targets.second, mPos[1]);
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 068efa6..aeca840 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -25,6 +25,7 @@
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
@@ -66,26 +67,11 @@
     private QSContainer mQsContainer;
 
     public QSCustomizer(Context context, AttributeSet attrs) {
-        super(new ContextThemeWrapper(context, android.R.style.Theme_Material), attrs);
+        super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
         mClipper = new QSDetailClipper(this);
-    }
 
-    public void setHost(QSTileHost host) {
-        mHost = host;
-        mPhoneStatusBar = host.getPhoneStatusBar();
-    }
+        LayoutInflater.from(getContext()).inflate(R.layout.qs_customize_panel_content, this);
 
-    public void setContainer(NotificationsQuickSettingsContainer notificationsQsContainer) {
-        mNotifQsContainer = notificationsQsContainer;
-    }
-
-    public void setQsContainer(QSContainer qsContainer) {
-        mQsContainer = qsContainer;
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
         mToolbar = (Toolbar) findViewById(com.android.internal.R.id.action_bar);
         TypedValue value = new TypedValue();
         mContext.getTheme().resolveAttribute(android.R.attr.homeAsUpIndicator, value, true);
@@ -115,6 +101,19 @@
         mRecyclerView.setItemAnimator(animator);
     }
 
+    public void setHost(QSTileHost host) {
+        mHost = host;
+        mPhoneStatusBar = host.getPhoneStatusBar();
+    }
+
+    public void setContainer(NotificationsQuickSettingsContainer notificationsQsContainer) {
+        mNotifQsContainer = notificationsQsContainer;
+    }
+
+    public void setQsContainer(QSContainer qsContainer) {
+        mQsContainer = qsContainer;
+    }
+
     public void show(int x, int y) {
         if (!isShown) {
             isShown = true;
@@ -129,6 +128,7 @@
     public void hide(int x, int y) {
         if (isShown) {
             isShown = false;
+            mToolbar.dismissPopupMenus();
             setCustomizing(false);
             save();
             mClipper.animateCircularClip(x, y, false, mCollapseAnimationListener);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index d9b3b3f..57db3a6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -28,6 +28,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
+import android.widget.TextView;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSIconView;
 import com.android.systemui.qs.QSTileView;
@@ -153,7 +154,12 @@
 
     @Override
     public void onBindViewHolder(final Holder holder, int position) {
-        if (holder.getItemViewType() == TYPE_EDIT) return;
+        if (holder.getItemViewType() == TYPE_EDIT) {
+            ((TextView) holder.itemView.findViewById(android.R.id.title)).setText(
+                    mCurrentDrag != null ? R.string.drag_to_remove_tiles
+                    : R.string.drag_to_add_tiles);
+            return;
+        }
 
         TileInfo info = mTiles.get(position);
         holder.mTileView.onStateChanged(info.state);
@@ -250,11 +256,13 @@
             super.onSelectedChanged(viewHolder, actionState);
             if (mCurrentDrag != null) {
                 mCurrentDrag.stopDrag();
+                mCurrentDrag = null;
             }
             if (viewHolder != null) {
                 mCurrentDrag = (Holder) viewHolder;
                 mCurrentDrag.startDrag();
             }
+            notifyItemChanged(mDividerIndex);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index fa235d3..74b3fdc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -73,6 +73,15 @@
     }
 
     @Override
+    protected String composeChangeAnnouncement() {
+        if (mState.value) {
+            return mContext.getString(R.string.accessibility_quick_settings_data_saver_changed_on);
+        } else {
+            return mContext.getString(R.string.accessibility_quick_settings_data_saver_changed_off);
+        }
+    }
+
+    @Override
     public void onDataSaverChanged(boolean isDataSaving) {
         refreshState(isDataSaving);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index da77dfd..2b6ed44 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -23,7 +23,9 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.content.res.Configuration;
+import android.graphics.Point;
 import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
 import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
@@ -43,6 +45,7 @@
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.SystemUI;
 import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
 import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
 import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
@@ -389,6 +392,13 @@
             return false;
         }
 
+        Point realSize = new Point();
+        if (initialBounds == null) {
+            mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
+                    .getRealSize(realSize);
+            initialBounds = new Rect(0, 0, realSize.x, realSize.y);
+        }
+
         int currentUser = sSystemServicesProxy.getCurrentUser();
         SystemServicesProxy ssp = Recents.getSystemServices();
         ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();
@@ -610,6 +620,12 @@
         }
     }
 
+    public final void onBusEvent(ConfigurationChangedEvent event) {
+        // Update the configuration for the Recents component when the activity configuration
+        // changes as well
+        mImpl.onConfigurationChanged();
+    }
+
     /**
      * Attempts to register with the system user.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index cd1a27f..f33ef65 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -26,6 +26,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.Configuration;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.SystemClock;
@@ -361,7 +362,8 @@
         RecentsConfiguration config = Recents.getConfiguration();
         RecentsActivityLaunchState launchState = config.getLaunchState();
         if (!loadPlan.hasTasks()) {
-            loader.preloadTasks(loadPlan, -1, launchState.launchedFromHome);
+            loader.preloadTasks(loadPlan, launchState.launchedToTaskId,
+                    launchState.launchedFromHome);
         }
 
         RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
@@ -431,13 +433,13 @@
 
         mIgnoreAltTabRelease = false;
         mIterateTrigger.stopDozing();
+    }
 
-        // Workaround for b/22542869, if the RecentsActivity is started again, but without going
-        // through SystemUI, we need to reset the config launch flags to ensure that we do not
-        // wait on the system to send a signal that was never queued.
-        RecentsConfiguration config = Recents.getConfiguration();
-        RecentsActivityLaunchState launchState = config.getLaunchState();
-        launchState.reset();
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+
+        EventBus.getDefault().send(new ConfigurationChangedEvent());
     }
 
     @Override
@@ -453,6 +455,13 @@
         mIsVisible = false;
         EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
         MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
+
+        // Workaround for b/22542869, if the RecentsActivity is started again, but without going
+        // through SystemUI, we need to reset the config launch flags to ensure that we do not
+        // wait on the system to send a signal that was never queued.
+        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsActivityLaunchState launchState = config.getLaunchState();
+        launchState.reset();
     }
 
     @Override
@@ -740,7 +749,7 @@
     public final void onBusEvent(AllTaskViewsDismissedEvent event) {
         SystemServicesProxy ssp = Recents.getSystemServices();
         if (ssp.hasDockedTask()) {
-            mRecentsView.showEmptyView();
+            mRecentsView.showEmptyView(R.string.recents_empty_message_dismissed_all);
         } else {
             // Just go straight home (no animation necessary because there are no more task views)
             dismissRecentsToHome(false /* animateTaskViews */);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
index 6feda81..40bf6d3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
@@ -41,6 +41,8 @@
         public static final boolean EnableHistory = false;
         // Overrides the Tuner flags and enables the timeout
         private static final boolean EnableFastToggleTimeout = false;
+        // Overrides the Tuner flags and enables the paging via the Recents button
+        private static final boolean EnablePaging = false;
 
         // Enables us to create mock recents tasks
         public static final boolean EnableMockTasks = false;
@@ -54,10 +56,6 @@
         public static final int MockTaskGroupsTaskCount = 12;
     }
 
-    private static final String KEY_ENABLE_PAGING = "overview_enable_paging";
-
-    private boolean mEnablePaging;
-
     /**
      * We read the prefs once when we start the activity, then update them as the tuner changes
      * the flags.
@@ -65,7 +63,6 @@
     public RecentsDebugFlags(Context context) {
         // Register all our flags, this will also call onTuningChanged() for each key, which will
         // initialize the current state of each flag
-        TunerService.get(context).addTunable(this, KEY_ENABLE_PAGING);
     }
 
     /**
@@ -83,16 +80,11 @@
      * @return whether we are enabling paging.
      */
     public boolean isPagingEnabled() {
-        return mEnablePaging;
+        return Static.EnablePaging;
     }
 
     @Override
     public void onTuningChanged(String key, String newValue) {
-        switch (key) {
-            case KEY_ENABLE_PAGING:
-                mEnablePaging = (newValue != null) && (Integer.parseInt(newValue) != 0);
-                break;
-        }
         EventBus.getDefault().send(new DebugFlagsChangedEvent());
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 4e11bca..d864df8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -759,6 +759,7 @@
             TaskStackLayoutAlgorithm stackLayout = stackView.getStackAlgorithm();
             TaskStackViewScroller stackScroller = stackView.getScroller();
 
+            stackView.updateLayoutAlgorithm(true /* boundScroll */);
             stackView.updateToInitialState();
 
             for (int i = tasks.size() - 1; i >= 0; i--) {
@@ -825,6 +826,7 @@
         }
 
         // Get the transform for the running task
+        stackView.updateLayoutAlgorithm(true /* boundScroll */);
         stackView.updateToInitialState();
         mTmpTransform = stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask,
                 stackView.getScroller().getStackScroll(), mTmpTransform, null);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 5e1af12..ee4d95e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -268,6 +268,14 @@
     BitmapDrawable mDefaultIcon;
     Bitmap mDefaultThumbnail;
 
+    private TaskKeyLruCache.EvictionCallback mClearActivityInfoOnEviction =
+            new TaskKeyLruCache.EvictionCallback() {
+        @Override
+        public void onEntryEvicted(Task.TaskKey key) {
+            mActivityInfoCache.remove(key.getComponent());
+        }
+    };
+
     public RecentsTaskLoader(Context context) {
         Resources res = context.getResources();
         mDefaultTaskBarBackgroundColor =
@@ -292,10 +300,11 @@
         // Initialize the proxy, cache and loaders
         int numRecentTasks = ActivityManager.getMaxRecentTasksStatic();
         mLoadQueue = new TaskResourceLoadQueue();
-        mIconCache = new TaskKeyLruCache<>(iconCacheSize);
+        mIconCache = new TaskKeyLruCache<>(iconCacheSize, mClearActivityInfoOnEviction);
         mThumbnailCache = new TaskKeyLruCache<>(thumbnailCacheSize);
-        mActivityLabelCache = new TaskKeyLruCache<>(numRecentTasks);
-        mContentDescriptionCache = new TaskKeyLruCache<>(numRecentTasks);
+        mActivityLabelCache = new TaskKeyLruCache<>(numRecentTasks, mClearActivityInfoOnEviction);
+        mContentDescriptionCache = new TaskKeyLruCache<>(numRecentTasks,
+                mClearActivityInfoOnEviction);
         mActivityInfoCache = new LruCache(numRecentTasks);
         mLoader = new BackgroundTaskLoader(mLoadQueue, mIconCache, mThumbnailCache,
                 mDefaultThumbnail, mDefaultIcon);
@@ -375,7 +384,6 @@
         mIconCache.remove(t.key);
         mActivityLabelCache.remove(t.key);
         mContentDescriptionCache.remove(t.key);
-        mActivityInfoCache.remove(t.key.getComponent());
         if (notifyTaskDataUnloaded) {
             t.notifyTaskDataUnloaded(null, mDefaultIcon);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java
index d433b6c0..748d8ed 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java
@@ -30,16 +30,29 @@
  */
 public class TaskKeyLruCache<V> {
 
+    public interface EvictionCallback {
+        public void onEntryEvicted(Task.TaskKey key);
+    }
+
     private static final String TAG = "TaskKeyLruCache";
 
     private final SparseArray<Task.TaskKey> mKeys = new SparseArray<>();
     private final LruCache<Integer, V> mCache;
+    private final EvictionCallback mEvictionCallback;
 
     public TaskKeyLruCache(int cacheSize) {
+        this(cacheSize, null);
+    }
+
+    public TaskKeyLruCache(int cacheSize, EvictionCallback evictionCallback) {
+        mEvictionCallback = evictionCallback;
         mCache = new LruCache<Integer, V>(cacheSize) {
 
             @Override
             protected void entryRemoved(boolean evicted, Integer taskId, V oldV, V newV) {
+                if (mEvictionCallback != null) {
+                    mEvictionCallback.onEntryEvicted(mKeys.get(taskId));
+                }
                 mKeys.remove(taskId);
             }
         };
@@ -84,8 +97,9 @@
 
     /** Removes a cache entry for a specific key. */
     final void remove(Task.TaskKey key) {
-        mKeys.remove(key.id);
+        // Remove the key after the cache value because we need it to make the callback
         mCache.remove(key.id);
+        mKeys.remove(key.id);
     }
 
     /** Removes all the entries in the cache. */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index dd825cb..a91bbd4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -105,6 +105,9 @@
             animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
                 @Override
                 public void onAnimationStarted() {
+                    // If we are launching into another task, cancel the previous task's
+                    // window transition
+                    EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
                     EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
 
                     if (screenPinningRequested) {
@@ -119,6 +122,9 @@
             animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
                 @Override
                 public void onAnimationStarted() {
+                    // If we are launching into another task, cancel the previous task's
+                    // window transition
+                    EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
                     EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
                 }
             };
@@ -146,10 +152,6 @@
                         animStartedListener);
             }
         }
-
-        // If we are launching into another task, cancel the previous task's
-        // window transition
-        EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
     }
 
     /**
@@ -278,7 +280,8 @@
             } else {
                 layoutAlgorithm.getStackTransformScreenCoordinates(task, stackScroll, mTmpTransform,
                         null);
-                specs.add(composeAnimationSpec(taskView, mTmpTransform, true /* addHeaderBitmap */));
+                specs.add(composeAnimationSpec(stackView, taskView, mTmpTransform,
+                        true /* addHeaderBitmap */));
             }
             return specs;
         }
@@ -299,7 +302,8 @@
                 } else {
                     layoutAlgorithm.getStackTransformScreenCoordinates(t, stackScroll,
                             mTmpTransform, null);
-                    specs.add(composeAnimationSpec(tv, mTmpTransform, true /* addHeaderBitmap */));
+                    specs.add(composeAnimationSpec(stackView, tv, mTmpTransform,
+                            true /* addHeaderBitmap */));
                 }
             }
         }
@@ -318,8 +322,8 @@
     /**
      * Composes a single animation spec for the given {@link TaskView}
      */
-    private static AppTransitionAnimationSpec composeAnimationSpec(TaskView taskView,
-            TaskViewTransform transform, boolean addHeaderBitmap) {
+    private static AppTransitionAnimationSpec composeAnimationSpec(TaskStackView stackView,
+            TaskView taskView, TaskViewTransform transform, boolean addHeaderBitmap) {
         Bitmap b = null;
         if (addHeaderBitmap) {
             float scale = transform.scale;
@@ -341,6 +345,10 @@
 
         Rect taskRect = new Rect();
         transform.rect.round(taskRect);
+        if (stackView.getStack().getStackFrontMostTask(false /* includeFreeformTasks */) !=
+                taskView.getTask()) {
+            taskRect.bottom = 2 * Recents.getSystemServices().getDisplayRect().height();
+        }
         return new AppTransitionAnimationSpec(taskView.getTask().key.id, b, taskRect);
     }
 }
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 8342de5..9235673 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -97,7 +97,7 @@
     private RecentsAppWidgetHostView mSearchBar;
     private TextView mHistoryButton;
     private TextView mHistoryClearAllButton;
-    private View mEmptyView;
+    private TextView mEmptyView;
     private RecentsHistoryView mHistoryView;
 
     private boolean mAwaitingFirstLayout = true;
@@ -159,7 +159,7 @@
                 }
             });
         }
-        mEmptyView = inflater.inflate(R.layout.recents_empty, this, false);
+        mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false);
         addView(mEmptyView);
 
         setBackground(mBackgroundScrim);
@@ -206,7 +206,7 @@
         if (stack.getTaskCount() > 0) {
             hideEmptyView();
         } else {
-            showEmptyView();
+            showEmptyView(R.string.recents_empty_message);
         }
     }
 
@@ -327,11 +327,12 @@
     /**
      * Hides the task stack and shows the empty view.
      */
-    public void showEmptyView() {
+    public void showEmptyView(int msgResId) {
         if (RecentsDebugFlags.Static.EnableSearchBar && (mSearchBar != null)) {
             mSearchBar.setVisibility(View.INVISIBLE);
         }
         mTaskStackView.setVisibility(View.INVISIBLE);
+        mEmptyView.setText(msgResId);
         mEmptyView.setVisibility(View.VISIBLE);
         mEmptyView.bringToFront();
         if (RecentsDebugFlags.Static.EnableHistory) {
@@ -400,8 +401,8 @@
 
         // Measure the empty view to the full size of the screen
         if (mEmptyView.getVisibility() != GONE) {
-            measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
-                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+            measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
+                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
         }
 
         if (RecentsDebugFlags.Static.EnableHistory) {
@@ -449,7 +450,13 @@
 
         // Layout the empty view
         if (mEmptyView.getVisibility() != GONE) {
-            mEmptyView.layout(left, top, right, bottom);
+            int leftRightInsets = mSystemInsets.left + mSystemInsets.right;
+            int topBottomInsets = mSystemInsets.top + mSystemInsets.bottom;
+            int childWidth = mEmptyView.getMeasuredWidth();
+            int childHeight = mEmptyView.getMeasuredHeight();
+            int childLeft = left + Math.max(0, (right - left - leftRightInsets - childWidth)) / 2;
+            int childTop = top + Math.max(0, (bottom - top - topBottomInsets - childHeight)) / 2;
+            mEmptyView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
         }
 
         if (RecentsDebugFlags.Static.EnableHistory) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index 079d7b9..84590f2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.recents.views;
 
+import android.app.ActivityManager;
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.view.MotionEvent;
@@ -149,7 +150,8 @@
         mTaskView.setTranslationY(y);
 
         mVisibleDockStates.clear();
-        if (!ssp.hasDockedTask() && mRv.getTaskStack().getTaskCount() > 1) {
+        if (ActivityManager.supportsMultiWindow() &&
+                !ssp.hasDockedTask() && mRv.getTaskStack().getTaskCount() > 1) {
             if (!event.task.isDockable) {
                 Toast.makeText(mRv.getContext(), R.string.recents_drag_non_dockable_task_message,
                         Toast.LENGTH_SHORT).show();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index a5ed32a..6df5884 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -222,9 +222,11 @@
     private Range mUnfocusedRange;
     private Range mFocusedRange;
 
-    // The initial offset from the top of the stack
+    // The initial offset from the top and bottom of the stack
     @ViewDebug.ExportedProperty(category="recents")
     private int mInitialTopPeekHeight;
+    @ViewDebug.ExportedProperty(category="recents")
+    private int mInitialBottomPeekHeight;
 
     // The offset from the top when scrolled to the top of the stack
     @ViewDebug.ExportedProperty(category="recents")
@@ -322,6 +324,8 @@
                 res.getFloat(R.integer.recents_layout_unfocused_range_max));
         mFocusState = getInitialFocusState();
         mInitialTopPeekHeight = res.getDimensionPixelSize(R.dimen.recents_initial_top_peek_size);
+        mInitialBottomPeekHeight =
+                res.getDimensionPixelSize(R.dimen.recents_initial_bottom_peek_size);
         mFocusedTopPeekHeight =
                 res.getDimensionPixelSize(R.dimen.recents_layout_focused_top_peek_size);
         mFocusedBottomTaskPeekHeight =
@@ -508,10 +512,13 @@
             float initialPeekOffsetNormX = mUnfocusedCurveInterpolator.getX(initialPeekOffsetPct);
             float initialFocusedOffset = mStackRect.height() - mInitialTopPeekHeight -
                     (mHeaderBarHeight * 1f) + 1;
-            float initialFocusedOffsetPct = (float) initialFocusedOffset / mStackRect.height();
+            float initialFocusedOffsetPct = initialFocusedOffset / mStackRect.height();
             float initialFocusedNormX = mUnfocusedCurveInterpolator.getX(initialFocusedOffsetPct);
-            int initialBottomOffset = mStackBottomOffset + mHeaderBarHeight;
-            float initialBottomOffsetPct = (float) initialBottomOffset / mStackRect.height();
+            float initialBottomOffset = mStackBottomOffset +
+                    (ssp.hasDockedTask()
+                        ? mHeaderBarHeight
+                        : mInitialBottomPeekHeight);
+            float initialBottomOffsetPct = initialBottomOffset / mStackRect.height();
             float initialBottomNormX = mUnfocusedCurveInterpolator.getX(initialBottomOffsetPct);
             /*
             // If we want to offset the top card slightly
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 e2830a1..93b5b6c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -61,6 +61,7 @@
 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
 import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
 import com.android.systemui.recents.events.activity.HideHistoryEvent;
+import com.android.systemui.recents.events.activity.HideRecentsEvent;
 import com.android.systemui.recents.events.activity.IterateRecentsEvent;
 import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskEvent;
@@ -113,6 +114,9 @@
     private static final int DRAG_SCALE_DURATION = 175;
     private static final float DRAG_SCALE_FACTOR = 1.05f;
 
+    private static final int LAUNCH_NEXT_SCROLL_BASE_DURATION = 200;
+    private static final int LAUNCH_NEXT_SCROLL_INCR_DURATION = 32;
+
     private static final ArraySet<Task.TaskKey> EMPTY_TASK_SET = new ArraySet<>();
 
     LayoutInflater mInflater;
@@ -813,7 +817,7 @@
      *
      * @see #updateLayoutAlgorithm(boolean, ArraySet<Task.TaskKey>)
      */
-    void updateLayoutAlgorithm(boolean boundScrollToNewMinMax) {
+   public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax) {
         updateLayoutAlgorithm(boundScrollToNewMinMax, mIgnoreTasks);
     }
 
@@ -822,7 +826,7 @@
      *
      * @param ignoreTasksSet the set of tasks to ignore in the relayout
      */
-    void updateLayoutAlgorithm(boolean boundScrollToNewMinMax,
+    public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax,
             ArraySet<Task.TaskKey> ignoreTasksSet) {
         // Compute the min and max scroll values
         mLayoutAlgorithm.update(mStack, ignoreTasksSet);
@@ -1618,12 +1622,34 @@
             mUIDozeTrigger.stopDozing();
             cancelAllTaskViewAnimations();
 
-            Task launchTask = mStack.getStackTasks().get(launchTaskIndex);
-            EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(launchTask),
-                    launchTask, null, INVALID_STACK_ID, false /* screenPinningRequested */));
+            final Task launchTask = mStack.getStackTasks().get(launchTaskIndex);
+            if (getChildViewForTask(launchTask) == null) {
+                List<TaskView> taskViews = getTaskViews();
+                int lastTaskIndex = !taskViews.isEmpty()
+                        ? mStack.indexOfStackTask(taskViews.get(taskViews.size() - 1).getTask())
+                        : mStack.getTaskCount() - 1;
+                int duration = LAUNCH_NEXT_SCROLL_BASE_DURATION +
+                        Math.abs(mStack.indexOfStackTask(launchTask) - lastTaskIndex)
+                                * LAUNCH_NEXT_SCROLL_INCR_DURATION;
+                mStackScroller.animateScroll(mLayoutAlgorithm.getStackScrollForTask(launchTask),
+                        duration, new Runnable() {
+                            @Override
+                            public void run() {
+                                EventBus.getDefault().send(new LaunchTaskEvent(
+                                        getChildViewForTask(launchTask), launchTask, null,
+                                        INVALID_STACK_ID, false /* screenPinningRequested */));
+                            }
+                        });
+            } else {
+                EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(launchTask),
+                        launchTask, null, INVALID_STACK_ID, false /* screenPinningRequested */));
+            }
 
             MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
                     launchTask.key.getComponent().toString());
+        } else if (mStack.getTaskCount() == 0) {
+            // If there are no tasks, then just hide recents back to home.
+            EventBus.getDefault().send(new HideRecentsEvent(false, true));
         }
     }
 
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 ad46abd..9be3542 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -179,6 +179,13 @@
 
     /** Animates the stack scroll */
     void animateScroll(float newScroll, final Runnable postRunnable) {
+        int duration = mContext.getResources().getInteger(
+                R.integer.recents_animate_task_stack_scroll_duration);
+        animateScroll(newScroll, duration, postRunnable);
+    }
+
+    /** Animates the stack scroll */
+    void animateScroll(float newScroll, int duration, final Runnable postRunnable) {
         // Finish any current scrolling animations
         if (mScrollAnimator != null && mScrollAnimator.isRunning()) {
             setStackScroll(mFinalAnimatedScroll);
@@ -190,8 +197,7 @@
         if (Float.compare(mStackScrollP, newScroll) != 0) {
             mFinalAnimatedScroll = newScroll;
             mScrollAnimator = ObjectAnimator.ofFloat(this, STACK_SCROLL, getStackScroll(), newScroll);
-            mScrollAnimator.setDuration(mContext.getResources().getInteger(
-                    R.integer.recents_animate_task_stack_scroll_duration));
+            mScrollAnimator.setDuration(duration);
             mScrollAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
             mScrollAnimator.addListener(new AnimatorListenerAdapter() {
                 @Override
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index e64354c..eb08947 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -93,13 +93,13 @@
 /**
  * An AsyncTask that saves an image to the media store in the background.
  */
-class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Void,
-        SaveImageInBackgroundData> {
+class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
 
     private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
     private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
     private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
 
+    private final SaveImageInBackgroundData mParams;
     private final NotificationManager mNotificationManager;
     private final Notification.Builder mNotificationBuilder, mPublicNotificationBuilder;
     private final File mScreenshotDir;
@@ -122,6 +122,7 @@
         Resources r = context.getResources();
 
         // Prepare all the output metadata
+        mParams = data;
         mImageTime = System.currentTimeMillis();
         String imageDate = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(mImageTime));
         mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
@@ -210,17 +211,17 @@
     }
 
     @Override
-    protected SaveImageInBackgroundData doInBackground(SaveImageInBackgroundData... params) {
+    protected Void doInBackground(Void... params) {
         if (isCancelled()) {
-            return params[0];
+            return null;
         }
 
         // By default, AsyncTask sets the worker thread to have background thread priority, so bump
         // it back up so that we save a little quicker.
         Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
 
-        Context context = params[0].context;
-        Bitmap image = params[0].image;
+        Context context = mParams.context;
+        Bitmap image = mParams.image;
         Resources r = context.getResources();
 
         try {
@@ -284,14 +285,14 @@
                     r.getString(com.android.internal.R.string.delete), deleteAction);
             mNotificationBuilder.addAction(deleteActionBuilder.build());
 
-            params[0].imageUri = uri;
-            params[0].image = null;
-            params[0].errorMsgResId = 0;
+            mParams.imageUri = uri;
+            mParams.image = null;
+            mParams.errorMsgResId = 0;
         } catch (Exception e) {
             // IOException/UnsupportedOperationException may be thrown if external storage is not
             // mounted
-            params[0].clearImage();
-            params[0].errorMsgResId = R.string.screenshot_failed_to_save_text;
+            mParams.clearImage();
+            mParams.errorMsgResId = R.string.screenshot_failed_to_save_text;
         }
 
         // Recycle the bitmap data
@@ -299,23 +300,23 @@
             image.recycle();
         }
 
-        return params[0];
+        return null;
     }
 
     @Override
-    protected void onPostExecute(SaveImageInBackgroundData params) {
-        if (params.errorMsgResId != 0) {
+    protected void onPostExecute(Void params) {
+        if (mParams.errorMsgResId != 0) {
             // Show a message that we've failed to save the image to disk
-            GlobalScreenshot.notifyScreenshotError(params.context, mNotificationManager,
-                    params.errorMsgResId);
+            GlobalScreenshot.notifyScreenshotError(mParams.context, mNotificationManager,
+                    mParams.errorMsgResId);
         } else {
             // Show the final notification to indicate screenshot saved
-            Context context = params.context;
+            Context context = mParams.context;
             Resources r = context.getResources();
 
             // Create the intent to show the screenshot in gallery
             Intent launchIntent = new Intent(Intent.ACTION_VIEW);
-            launchIntent.setDataAndType(params.imageUri, "image/png");
+            launchIntent.setDataAndType(mParams.imageUri, "image/png");
             launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
             final long now = System.currentTimeMillis();
@@ -324,7 +325,7 @@
             mPublicNotificationBuilder
                     .setContentTitle(r.getString(R.string.screenshot_saved_title))
                     .setContentText(r.getString(R.string.screenshot_saved_text))
-                    .setContentIntent(PendingIntent.getActivity(params.context, 0, launchIntent, 0))
+                    .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
                     .setWhen(now)
                     .setAutoCancel(true)
                     .setColor(context.getColor(
@@ -332,7 +333,7 @@
             mNotificationBuilder
                 .setContentTitle(r.getString(R.string.screenshot_saved_title))
                 .setContentText(r.getString(R.string.screenshot_saved_text))
-                .setContentIntent(PendingIntent.getActivity(params.context, 0, launchIntent, 0))
+                .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
                 .setWhen(now)
                 .setAutoCancel(true)
                 .setColor(context.getColor(
@@ -342,15 +343,18 @@
 
             mNotificationManager.notify(R.id.notification_screenshot, mNotificationBuilder.build());
         }
-        params.finisher.run();
-        params.clearContext();
+        mParams.finisher.run();
+        mParams.clearContext();
     }
 
     @Override
-    protected void onCancelled(SaveImageInBackgroundData params) {
-        params.finisher.run();
-        params.clearImage();
-        params.clearContext();
+    protected void onCancelled(Void params) {
+        // If we are cancelled while the task is running in the background, we may get null params.
+        // The finisher is expected to always be called back, so just use the baked-in params from
+        // the ctor in any case.
+        mParams.finisher.run();
+        mParams.clearImage();
+        mParams.clearContext();
 
         // Cancel the posted notification
         mNotificationManager.cancel(R.id.notification_screenshot);
@@ -419,7 +423,7 @@
     private float mBgPadding;
     private float mBgPaddingScale;
 
-    private AsyncTask<SaveImageInBackgroundData, Void, SaveImageInBackgroundData> mSaveInBgTask;
+    private AsyncTask<Void, Void, Void> mSaveInBgTask;
 
     private MediaActionSound mCameraSound;
 
@@ -510,7 +514,7 @@
             mSaveInBgTask.cancel(false);
         }
         mSaveInBgTask = new SaveImageInBackgroundTask(mContext, data, mNotificationManager)
-                .execute(data);
+                .execute();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java
new file mode 100644
index 0000000..fc2a1e4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 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.screenshot;
+
+import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.systemui.R;
+
+/**
+ * Performs a number of miscellaneous, non-system-critical actions
+ * after the system has finished booting.
+ */
+public class ScreenshotServiceErrorReceiver extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(final Context context, Intent intent) {
+        // Show a message that we've failed to save the image to disk
+        NotificationManager nm = (NotificationManager)
+                context.getSystemService(Context.NOTIFICATION_SERVICE);
+        GlobalScreenshot.notifyScreenshotError(context, nm,
+                R.string.screenshot_failed_to_save_unknown_text);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 8f8683b..69dcabe 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -17,18 +17,31 @@
 package com.android.systemui.shortcut;
 
 import android.accessibilityservice.AccessibilityServiceInfo;
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ServiceInfo;
+import android.content.res.Configuration;
 import android.os.RemoteException;
+import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.IWindowManager;
 import android.view.KeyEvent;
+import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityManager;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.settingslib.accessibility.AccessibilityUtils;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.stackdivider.DividerView;
+import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
 
 import java.util.List;
 import java.util.Set;
@@ -42,28 +55,70 @@
     private static final String TAG = "ShortcutKeyDispatcher";
 
     private ShortcutKeyServiceProxy mShortcutKeyServiceProxy = new ShortcutKeyServiceProxy(this);
-    private IWindowManager windowManagerService = WindowManagerGlobal.getWindowManagerService();
+    private IWindowManager mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
+    private IActivityManager mActivityManager = ActivityManagerNative.getDefault();
 
     protected final long META_MASK = ((long) KeyEvent.META_META_ON) << Integer.SIZE;
     protected final long ALT_MASK = ((long) KeyEvent.META_ALT_ON) << Integer.SIZE;
     protected final long CTRL_MASK = ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE;
     protected final long SHIFT_MASK = ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE;
 
+    protected final long SC_DOCK_LEFT = META_MASK | KeyEvent.KEYCODE_LEFT_BRACKET;
+    protected final long SC_DOCK_RIGHT = META_MASK | KeyEvent.KEYCODE_RIGHT_BRACKET;
+
     /**
      * Registers a shortcut key to window manager.
      * @param shortcutCode packed representation of shortcut key code and meta information
      */
     public void registerShortcutKey(long shortcutCode) {
         try {
-            windowManagerService.registerShortcutKey(shortcutCode, mShortcutKeyServiceProxy);
+            mWindowManagerService.registerShortcutKey(shortcutCode, mShortcutKeyServiceProxy);
         } catch (RemoteException e) {
             // Do nothing
         }
     }
 
     @Override
-    public void onShortcutKeyPressed(long shortcutCode) {}
+    public void onShortcutKeyPressed(long shortcutCode) {
+        int orientation = mContext.getResources().getConfiguration().orientation;
+        if ((shortcutCode == SC_DOCK_LEFT || shortcutCode == SC_DOCK_RIGHT)
+                && orientation == Configuration.ORIENTATION_LANDSCAPE) {
+            handleDockKey(shortcutCode);
+        }
+    }
 
     @Override
-    public void start() {}
+    public void start() {
+        registerShortcutKey(SC_DOCK_LEFT);
+        registerShortcutKey(SC_DOCK_RIGHT);
+    }
+
+    private void handleDockKey(long shortcutCode) {
+        try {
+            int dockSide = mWindowManagerService.getDockedStackSide();
+            if (dockSide == WindowManager.DOCKED_INVALID) {
+                // If there is no window docked, we dock the top-most window.
+                Recents recents = getComponent(Recents.class);
+                int dockMode = (shortcutCode == SC_DOCK_LEFT)
+                        ? ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
+                        : ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
+                recents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE, dockMode, null);
+                MetricsLogger.action(mContext, MetricsEvent.WINDOW_DOCK_SHORTCUTS);
+            } else {
+                // If there is already a docked window, we respond by resizing the docking pane.
+                DividerView dividerView = getComponent(Divider.class).getView();
+                DividerSnapAlgorithm snapAlgorithm = dividerView.getSnapAlgorithm();
+                int dividerPosition = dividerView.getCurrentPosition();
+                DividerSnapAlgorithm.SnapTarget currentTarget =
+                        snapAlgorithm.calculateNonDismissingSnapTarget(dividerPosition);
+                int increment = (shortcutCode == SC_DOCK_LEFT) ? -1 : 1;
+                DividerSnapAlgorithm.SnapTarget target = snapAlgorithm.cycleNonDismissTarget(
+                        currentTarget, increment);
+                dividerView.startDragging(true /* animate */, false /* touching */);
+                dividerView.stopDragging(target.position, 0f, true /* avoidDismissStart */);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "handleDockKey() failed.");
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 7cb1f24..e015666 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.stackdivider;
 
+import static android.view.PointerIcon.STYLE_HORIZONTAL_DOUBLE_ARROW;
+import static android.view.PointerIcon.STYLE_VERTICAL_DOUBLE_ARROW;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
@@ -31,6 +34,9 @@
 import android.util.AttributeSet;
 import android.view.Display;
 import android.view.DisplayInfo;
+import android.view.GestureDetector;
+import android.view.GestureDetector.OnDoubleTapListener;
+import android.view.GestureDetector.SimpleOnGestureListener;
 import android.view.MotionEvent;
 import android.view.PointerIcon;
 import android.view.VelocityTracker;
@@ -39,6 +45,7 @@
 import android.view.ViewConfiguration;
 import android.view.ViewTreeObserver.InternalInsetsInfo;
 import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -52,17 +59,16 @@
 import com.android.internal.policy.DockedDividerUtils;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
 import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
 import com.android.systemui.recents.events.activity.UndockingTaskEvent;
 import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
 
-import static android.view.PointerIcon.STYLE_HORIZONTAL_DOUBLE_ARROW;
-import static android.view.PointerIcon.STYLE_VERTICAL_DOUBLE_ARROW;
-
 /**
  * Docked stack divider.
  */
@@ -136,6 +142,7 @@
     private boolean mGrowRecents;
     private ValueAnimator mCurrentAnimator;
     private boolean mEntranceAnimationRunning;
+    private GestureDetector mGestureDetector;
 
     private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
         @Override
@@ -213,12 +220,35 @@
                 landscape ? STYLE_HORIZONTAL_DOUBLE_ARROW : STYLE_VERTICAL_DOUBLE_ARROW));
         getViewTreeObserver().addOnComputeInternalInsetsListener(this);
         mHandle.setAccessibilityDelegate(mHandleDelegate);
+        mGestureDetector = new GestureDetector(mContext, new SimpleOnGestureListener() {
+            @Override
+            public boolean onSingleTapUp(MotionEvent e) {
+                updateDockSide();
+                SystemServicesProxy ssp = Recents.getSystemServices();
+                if (mDockSide != WindowManager.DOCKED_INVALID
+                        && !ssp.isRecentsTopMost(ssp.getTopMostTask(), null /* isTopHome */)) {
+                    mWindowManagerProxy.swapTasks();
+                    return true;
+                }
+                return false;
+            }
+        });
     }
 
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         EventBus.getDefault().register(this);
+        getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
+
+            @Override
+            public void onGlobalLayout() {
+                getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                mWindowManagerProxy.setTouchRegion(new Rect(mHandle.getLeft(), mHandle.getTop(),
+                        mHandle.getLeft() + mHandle.getWidth(),
+                        mHandle.getTop() + mHandle.getHeight()));
+            }
+        });
     }
 
     @Override
@@ -320,6 +350,7 @@
     @Override
     public boolean onTouch(View v, MotionEvent event) {
         convertToScreenCoordinates(event);
+        mGestureDetector.onTouchEvent(event);
         final int action = event.getAction() & MotionEvent.ACTION_MASK;
         switch (action) {
             case MotionEvent.ACTION_DOWN:
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 15bcaf8..e312fa2 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.stackdivider;
 
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.view.WindowManager.DOCKED_INVALID;
+
 import android.app.ActivityManagerNative;
 import android.graphics.Rect;
 import android.os.RemoteException;
@@ -27,9 +30,6 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.view.WindowManager.DOCKED_INVALID;
-
 /**
  * Proxy to simplify calls into window manager/activity manager
  */
@@ -39,7 +39,7 @@
 
     private static final WindowManagerProxy sInstance = new WindowManagerProxy();
 
-    @GuardedBy("mResizeRect")
+    @GuardedBy("mDockedRect")
     private final Rect mDockedRect = new Rect();
     private final Rect mTempDockedTaskRect = new Rect();
     private final Rect mTempDockedInsetRect = new Rect();
@@ -52,6 +52,9 @@
     private final Rect mTmpRect4 = new Rect();
     private final Rect mTmpRect5 = new Rect();
 
+    @GuardedBy("mDockedRect")
+    private final Rect mTouchableRegion = new Rect();
+
     private boolean mDimLayerVisible;
     private int mDimLayerTargetStack;
     private float mDimLayerAlpha;
@@ -117,6 +120,32 @@
         }
     };
 
+    private final Runnable mSwapRunnable = new Runnable() {
+        @Override
+        public void run() {
+            try {
+                ActivityManagerNative.getDefault().swapDockedAndFullscreenStack();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to resize stack: " + e);
+            }
+        }
+    };
+
+    private final Runnable mSetTouchableRegionRunnable = new Runnable() {
+        @Override
+        public void run() {
+            try {
+                synchronized (mDockedRect) {
+                    mTmpRect1.set(mTouchableRegion);
+                }
+                WindowManagerGlobal.getWindowManagerService().setDockedStackDividerTouchRegion(
+                        mTmpRect1);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to set touchable region: " + e);
+            }
+        }
+    };
+
     private WindowManagerProxy() {
     }
 
@@ -188,4 +217,15 @@
         mDimLayerAlpha = alpha;
         mExecutor.execute(mDimLayerRunnable);
     }
+
+    public void swapTasks() {
+        mExecutor.execute(mSwapRunnable);
+    }
+
+    public void setTouchRegion(Rect region) {
+        synchronized (mDockedRect) {
+            mTouchableRegion.set(region);
+        }
+        mExecutor.execute(mSetTouchableRegionRunnable);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 5652c7d..71f74cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -148,7 +148,7 @@
         public void onAnimationEnd(Animator animation) {
             super.onAnimationEnd(animation);
             mFadeInFromDarkAnimator = null;
-            updateOutlineAlpha();
+            updateBackground();
         }
     };
     private ValueAnimator.AnimatorUpdateListener mUpdateOutlineListener
@@ -340,9 +340,7 @@
             animator.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation) {
-                    if (mDimmed) {
-                        mBackgroundNormal.setVisibility(View.INVISIBLE);
-                    }
+                    updateBackground();
                 }
             });
             animator.start();
@@ -371,14 +369,14 @@
      */
     public void makeInactive(boolean animate) {
         if (mActivated) {
+            mActivated = false;
             if (mDimmed) {
                 if (animate) {
                     startActivateAnimation(true /* reverse */);
                 } else {
-                    mBackgroundNormal.setVisibility(View.INVISIBLE);
+                    updateBackground();
                 }
             }
-            mActivated = false;
         }
         if (mOnActivatedListener != null) {
             mOnActivatedListener.onActivationReset(this);
@@ -408,20 +406,9 @@
             return;
         }
         mDark = dark;
+        updateBackground();
         if (!dark && fade && !shouldHideBackground()) {
-            if (mActivated) {
-                mBackgroundDimmed.setVisibility(View.VISIBLE);
-                mBackgroundNormal.setVisibility(View.VISIBLE);
-            } else if (mDimmed) {
-                mBackgroundDimmed.setVisibility(View.VISIBLE);
-                mBackgroundNormal.setVisibility(View.INVISIBLE);
-            } else {
-                mBackgroundDimmed.setVisibility(View.INVISIBLE);
-                mBackgroundNormal.setVisibility(View.VISIBLE);
-            }
             fadeInFromDark(delay);
-        } else {
-            updateBackground();
         }
         updateOutlineAlpha();
     }
@@ -528,6 +515,7 @@
     private void fadeInFromDark(long delay) {
         final View background = mDimmed ? mBackgroundDimmed : mBackgroundNormal;
         background.setAlpha(0f);
+        mBackgroundVisibilityUpdater.onAnimationUpdate(null);
         background.setPivotX(mBackgroundDimmed.getWidth() / 2f);
         background.setPivotY(getActualHeight() / 2f);
         background.setScaleX(DARK_EXIT_SCALE_START);
@@ -565,6 +553,10 @@
     private void fadeDimmedBackground() {
         mBackgroundDimmed.animate().cancel();
         mBackgroundNormal.animate().cancel();
+        if (mActivated) {
+            updateBackground();
+            return;
+        }
         if (!shouldHideBackground()) {
             if (mDimmed) {
                 mBackgroundDimmed.setVisibility(View.VISIBLE);
@@ -594,11 +586,7 @@
         mBackgroundAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                if (mDimmed) {
-                    mBackgroundNormal.setVisibility(View.INVISIBLE);
-                } else {
-                    mBackgroundDimmed.setVisibility(View.INVISIBLE);
-                }
+                updateBackground();
                 mBackgroundAnimator = null;
             }
         });
@@ -613,12 +601,14 @@
             mBackgroundNormal.setVisibility(View.INVISIBLE);
         } else if (mDimmed) {
             mBackgroundDimmed.setVisibility(View.VISIBLE);
-            mBackgroundNormal.setVisibility(View.INVISIBLE);
+            mBackgroundNormal.setVisibility(mActivated ? View.VISIBLE : View.INVISIBLE);
         } else {
             mBackgroundDimmed.setVisibility(View.INVISIBLE);
             mBackgroundNormal.setVisibility(View.VISIBLE);
             mBackgroundNormal.setAlpha(1f);
             removeCallbacks(mTapTimeoutRunnable);
+            // make in inactive to avoid it sticking around active
+            makeInactive(false /* animate */);
         }
         setNormalBackgroundVisibilityAmount(
                 mBackgroundNormal.getVisibility() == View.VISIBLE ? 1.0f : 0.0f);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 143f160..a6c9f26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1856,15 +1856,16 @@
 
     /**
      * The LEDs are turned off when the notification panel is shown, even just a little bit.
+     * See also NotificationStackScrollLayout.setIsExpanded() for another place where we
+     * attempt to do this.
      */
     protected void handleVisibleToUserChanged(boolean visibleToUser) {
         try {
             if (visibleToUser) {
                 boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
                 boolean clearNotificationEffects =
-                    ((mShowLockscreenNotifications && mState == StatusBarState.KEYGUARD) ||
-                            (!pinnedHeadsUp && (mState == StatusBarState.SHADE
-                                    || mState == StatusBarState.SHADE_LOCKED)));
+                        !isPanelFullyCollapsed() &&
+                        (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED);
                 int notificationLoad = mNotificationData.getActiveNotifications().size();
                 if (pinnedHeadsUp && isPanelFullyCollapsed())  {
                     notificationLoad = 1;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index c2e1f7d..246f15e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -241,18 +241,22 @@
     }
 
     private void updateLimits() {
-        boolean customView = getPrivateLayout().getContractedChild().getId()
+        updateLimitsForView(mPrivateLayout);
+        updateLimitsForView(mPublicLayout);
+    }
+
+    private void updateLimitsForView(NotificationContentView layout) {
+        boolean customView = layout.getContractedChild().getId()
                 != com.android.internal.R.id.status_bar_latest_event_content;
         boolean beforeN = mEntry.targetSdk < Build.VERSION_CODES.N;
         int minHeight = customView && beforeN && !mIsSummaryWithChildren ?
                 mNotificationMinHeightLegacy : mNotificationMinHeight;
-        boolean headsUpCustom = getPrivateLayout().getHeadsUpChild() != null &&
-                getPrivateLayout().getHeadsUpChild().getId()
-                != com.android.internal.R.id.status_bar_latest_event_content;
+        boolean headsUpCustom = layout.getHeadsUpChild() != null &&
+                layout.getHeadsUpChild().getId()
+                        != com.android.internal.R.id.status_bar_latest_event_content;
         int headsUpheight = headsUpCustom && beforeN ? mMaxHeadsUpHeightLegacy
                 : mMaxHeadsUpHeight;
-        mPrivateLayout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight);
-        mPublicLayout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight);
+        layout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight);
     }
 
     public StatusBarNotification getStatusBarNotification() {
@@ -741,6 +745,9 @@
 
     public Animator getTranslateViewAnimator(final float leftTarget,
             AnimatorUpdateListener listener) {
+        if (mTranslateAnim != null) {
+            mTranslateAnim.cancel();
+        }
         if (areGutsExposed()) {
             // No translation if guts are exposed.
             return null;
@@ -765,19 +772,27 @@
                     if (listener != null) {
                         translateAnim.addUpdateListener(listener);
                     }
-                }
-                translateAnim.addListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator anim) {
-                        if (mSettingsIconRow != null && leftTarget == 0) {
-                            mSettingsIconRow.resetState();
+                    translateAnim.addListener(new AnimatorListenerAdapter() {
+                        boolean cancelled = false;
+
+                        @Override
+                        public void onAnimationCancel(Animator anim) {
+                            cancelled = true;
                         }
-                        mTranslateAnim = null;
-                    }
-                });
+
+                        @Override
+                        public void onAnimationEnd(Animator anim) {
+                            if (!cancelled && mSettingsIconRow != null && leftTarget == 0) {
+                                mSettingsIconRow.resetState();
+                                mTranslateAnim = null;
+                            }
+                        }
+                    });
+                }
                 set.play(translateAnim);
             }
         }
+        mTranslateAnim = set;
         return set;
     }
 
@@ -1349,7 +1364,7 @@
         float y = event.getY();
         NotificationHeaderView header = getVisibleNotificationHeader();
         if (header != null) {
-            return header.isInTouchRect(x, y);
+            return header.isInTouchRect(x - getTranslation(), y);
         }
         return super.disallowSingleClick(event);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index c0e4340..91418ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -43,6 +43,7 @@
     private boolean mWillBeGone;
     private int mMinClipTopAmount = 0;
     private boolean mClipToActualHeight = true;
+    private boolean mChangingPosition = false;
 
     public ExpandableView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -407,6 +408,14 @@
         return 0;
     }
 
+    public void setChangingPosition(boolean changingPosition) {
+        mChangingPosition = changingPosition;
+    }
+
+    public boolean isChangingPosition() {
+        return mChangingPosition;
+    }
+
     /**
      * A listener notifying when {@link #getActualHeight} changes.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
index 375459f..fcc48bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
@@ -29,11 +29,18 @@
 
 public class NotificationSettingsIconRow extends FrameLayout implements View.OnClickListener {
 
+    private static final int GEAR_ALPHA_ANIM_DURATION = 200;
+
     public interface SettingsIconRowListener {
         /**
          * Called when the gear behind a notification is touched.
          */
         public void onGearTouched(ExpandableNotificationRow row, int x, int y);
+
+        /**
+         * Called when a notification is slid back over the gear.
+         */
+        public void onSettingsIconRowReset(NotificationSettingsIconRow row);
     }
 
     private ExpandableNotificationRow mParent;
@@ -45,6 +52,8 @@
     private boolean mSettingsFadedIn = false;
     private boolean mAnimating = false;
     private boolean mOnLeft = true;
+    private boolean mDismissing = false;
+    private boolean mSnapping = false;
     private int[] mGearLocation = new int[2];
     private int[] mParentLocation = new int[2];
 
@@ -78,8 +87,14 @@
 
     public void resetState() {
         setGearAlpha(0f);
+        mSettingsFadedIn = false;
         mAnimating = false;
+        mSnapping = false;
+        mDismissing = false;
         setIconLocation(true /* on left */);
+        if (mListener != null) {
+            mListener.onSettingsIconRowReset(this);
+        }
     }
 
     public void setGearListener(SettingsIconRowListener listener) {
@@ -94,20 +109,24 @@
         return mParent;
     }
 
-    private void setGearAlpha(float alpha) {
+    public void setGearAlpha(float alpha) {
         if (alpha == 0) {
             mSettingsFadedIn = false; // Can fade in again once it's gone.
             setVisibility(View.INVISIBLE);
         } else {
-            if (alpha == 1) {
-                mSettingsFadedIn = true;
-            }
             setVisibility(View.VISIBLE);
         }
         mGearIcon.setAlpha(alpha);
     }
 
     /**
+     * Returns whether the icon is on the left side of the view or not.
+     */
+    public boolean isIconOnLeft() {
+        return mOnLeft;
+    }
+
+    /**
      * Returns the horizontal space in pixels required to display the gear behind a notification.
      */
     public float getSpaceForGear() {
@@ -119,7 +138,7 @@
      * if entire view is visible.
      */
     public boolean isVisible() {
-        return mSettingsFadedIn;
+        return mGearIcon.getAlpha() > 0;
     }
 
     public void cancelFadeAnimator() {
@@ -129,16 +148,18 @@
     }
 
     public void updateSettingsIcons(final float transX, final float size) {
-        if (mAnimating || (mGearIcon.getAlpha() == 0)) {
-            // Don't adjust when animating or settings aren't visible
+        if (mAnimating || !mSettingsFadedIn) {
+            // Don't adjust when animating, or if the gear hasn't been shown yet.
             return;
         }
-        setIconLocation(transX > 0 /* fromLeft */);
+
         final float fadeThreshold = size * 0.3f;
         final float absTrans = Math.abs(transX);
         float desiredAlpha = 0;
 
-        if (absTrans <= fadeThreshold) {
+        if (absTrans == 0) {
+            desiredAlpha = 0;
+        } else if (absTrans <= fadeThreshold) {
             desiredAlpha = 1;
         } else {
             desiredAlpha = 1 - ((absTrans - fadeThreshold) / (size - fadeThreshold));
@@ -148,6 +169,12 @@
 
     public void fadeInSettings(final boolean fromLeft, final float transX,
             final float notiThreshold) {
+        if (mDismissing || mAnimating) {
+            return;
+        }
+        if (isIconLocationChange(transX)) {
+            setGearAlpha(0f);
+        }
         setIconLocation(transX > 0 /* fromLeft */);
         mFadeAnimator = ValueAnimator.ofFloat(mGearIcon.getAlpha(), 1);
         mFadeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@@ -164,40 +191,53 @@
         });
         mFadeAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
-            public void onAnimationCancel(Animator animation) {
-                super.onAnimationCancel(animation);
-                mAnimating = false;
-                mSettingsFadedIn = false;
-            }
-
-            @Override
             public void onAnimationStart(Animator animation) {
-                super.onAnimationStart(animation);
                 mAnimating = true;
             }
 
             @Override
+            public void onAnimationCancel(Animator animation) {
+                // TODO should animate back to 0f from current alpha
+                mGearIcon.setAlpha(0f);
+            }
+
+            @Override
             public void onAnimationEnd(Animator animation) {
-                super.onAnimationEnd(animation);
                 mAnimating = false;
-                mSettingsFadedIn = true;
+                mSettingsFadedIn = mGearIcon.getAlpha() == 1;
             }
         });
         mFadeAnimator.setInterpolator(Interpolators.ALPHA_IN);
-        mFadeAnimator.setDuration(200);
+        mFadeAnimator.setDuration(GEAR_ALPHA_ANIM_DURATION);
         mFadeAnimator.start();
     }
 
-    private void setIconLocation(boolean onLeft) {
-        if (onLeft == mOnLeft) {
+    public void setIconLocation(boolean onLeft) {
+        if (onLeft == mOnLeft || mSnapping) {
             // Same side? Do nothing.
             return;
         }
-
         setTranslationX(onLeft ? 0 : (mParent.getWidth() - mHorizSpaceForGear));
         mOnLeft = onLeft;
     }
 
+    public boolean isIconLocationChange(float translation) {
+        boolean onLeft = translation > mGearIcon.getPaddingStart();
+        boolean onRight = translation < -mGearIcon.getPaddingStart();
+        if ((mOnLeft && onRight) || (!mOnLeft && onLeft)) {
+            return true;
+        }
+        return false;
+    }
+
+    public void setDismissing() {
+        mDismissing = true;
+    }
+
+    public void setSnapping(boolean snapping) {
+        mSnapping = snapping;
+    }
+
     @Override
     public void onClick(View v) {
         if (v.getId() == R.id.gear_icon) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
index 66f945e..f75f3574 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
@@ -188,6 +188,9 @@
 
     @Override
     public void setVisible(boolean visible) {
+        if (mViewTransformationAnimation != null) {
+            mViewTransformationAnimation.cancel();
+        }
         for (Integer viewType : mTransformedViews.keySet()) {
             TransformState ownState = getCurrentState(viewType);
             if (ownState != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
index 8a93c5b..bb43899 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
@@ -71,7 +71,6 @@
     private List<CarNavigationButton> mNavButtons = new ArrayList<CarNavigationButton>();
 
     private int mCurrentFacetIndex;
-    private String mCurrentPackageName;
     private SparseBooleanArray mFacetHasMultipleAppsCache = new SparseBooleanArray();
 
     public CarNavigationBarController(Context context,
@@ -84,7 +83,6 @@
     }
 
     public void taskChanged(String packageName) {
-        mCurrentPackageName = packageName;
         // If the package name belongs to a filter, then highlight appropriate button in
         // the navigation bar.
         if (mFacetPackageMap.containsKey(packageName)) {
@@ -298,12 +296,6 @@
             return;
         }
 
-        // Don't launch the lens picker if it's already running and the
-        // user clicks the same facet
-        if (packageName.equals(mCurrentPackageName) && index == mCurrentFacetIndex) {
-            return;
-        }
-
         intent.putExtra(EXTRA_FACET_CATEGORIES, mFacetCategories.get(index));
         intent.putExtra(EXTRA_FACET_PACKAGES, mFacetPackages.get(index));
         // The facet is identified by the index in which it was added to the nav bar.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
index d3393b3..20dbc4a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
@@ -46,7 +46,8 @@
             if(TextUtils.equals(otherTvs.mText.getText(), mText.getText())) {
                 int ownEllipsized = getEllipsisCount();
                 int otherEllipsized = otherTvs.getEllipsisCount();
-                return ownEllipsized == otherEllipsized;
+                return ownEllipsized == otherEllipsized
+                        && mText.getHeight() == otherTvs.mText.getHeight();
             }
         }
         return super.sameAs(otherState);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 5b4a3f0..65e7973 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -105,7 +105,6 @@
                 if (mSelectedUser != null && mSelectedUser.getIdentifier() != mCurrentUserId) {
                     // When selected user is different from the current user, show the selected
                     // user's static wallpaper.
-                    mWallpaperManager.forgetLoadedWallpaper();
                     mCache = mWallpaperManager.getBitmapAsUser(mSelectedUser.getIdentifier());
                 } else {
                     // When there is no selected user, or it's same as the current user, show the
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 d50e67a..e5e3caf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -277,11 +277,12 @@
     public void updateResources() {
         int panelWidth = getResources().getDimensionPixelSize(R.dimen.notification_panel_width);
         int panelGravity = getResources().getInteger(R.integer.notification_panel_layout_gravity);
-        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mQsContainer.getLayoutParams();
+        FrameLayout.LayoutParams lp =
+                (FrameLayout.LayoutParams) mQsDensityContainer.getLayoutParams();
         if (lp.width != panelWidth) {
             lp.width = panelWidth;
             lp.gravity = panelGravity;
-            mQsContainer.setLayoutParams(lp);
+            mQsDensityContainer.setLayoutParams(lp);
             mQsContainer.post(mUpdateHeader);
         }
 
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 6ad7aad..bf58611 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1012,7 +1012,7 @@
         }
     }
 
-    private void clearAllNotifications() {
+    public void clearAllNotifications() {
 
         // animate-swipe all dismissable notifications, then animate the shade closed
         int numChildren = mStackScroller.getChildCount();
@@ -1149,9 +1149,10 @@
 
         @Override
         public boolean onLongClick(View v) {
-            if (mRecents == null) {
+            if (mRecents == null || !ActivityManager.supportsMultiWindow()) {
                 return false;
             }
+
             boolean initiallyDocked = WindowManagerProxy.getInstance().getDockSide()
                     == WindowManager.DOCKED_INVALID;
             boolean dockedAtEnd = toggleSplitScreenMode();
@@ -1172,13 +1173,8 @@
         }
         int dockSide = WindowManagerProxy.getInstance().getDockSide();
         if (dockSide == WindowManager.DOCKED_INVALID) {
-            Point realSize = new Point();
-            mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
-                    .getRealSize(realSize);
-            Rect initialBounds= new Rect(0, 0, realSize.x, realSize.y);
             return mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE,
-                    ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
-                    initialBounds);
+                    ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null);
         } else {
             EventBus.getDefault().send(new UndockingTaskEvent());
             return false;
@@ -1891,10 +1887,16 @@
             if (mBackdrop.getVisibility() != View.VISIBLE) {
                 mBackdrop.setVisibility(View.VISIBLE);
                 if (allowEnterAnimation) {
-                    mBackdrop.animate().alpha(1f);
+                    mBackdrop.animate().alpha(1f).withEndAction(new Runnable() {
+                        @Override
+                        public void run() {
+                            mStatusBarWindowManager.setBackdropShowing(true);
+                        }
+                    });
                 } else {
                     mBackdrop.animate().cancel();
                     mBackdrop.setAlpha(1f);
+                    mStatusBarWindowManager.setBackdropShowing(true);
                 }
                 metaDataChanged = true;
                 if (DEBUG_MEDIA) {
@@ -1951,7 +1953,10 @@
 
                     // We are unlocking directly - no animation!
                     mBackdrop.setVisibility(View.GONE);
+                    mBackdropBack.setImageDrawable(null);
+                    mStatusBarWindowManager.setBackdropShowing(false);
                 } else {
+                    mStatusBarWindowManager.setBackdropShowing(false);
                     mBackdrop.animate()
                             // Never let the alpha become zero - otherwise the RenderNode
                             // won't draw anything and uninitialized memory will show through
@@ -1966,7 +1971,7 @@
                                 public void run() {
                                     mBackdrop.setVisibility(View.GONE);
                                     mBackdropFront.animate().cancel();
-                                    mBackdropBack.animate().cancel();
+                                    mBackdropBack.setImageDrawable(null);
                                     mHandler.post(mHideBackdropFront);
                                 }
                             });
@@ -3141,7 +3146,7 @@
         }
     };
 
-    private void resetUserExpandedStates() {
+    public void resetUserExpandedStates() {
         ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
         final int notificationCount = activeNotifications.size();
         for (int i = 0; i < notificationCount; i++) {
@@ -4494,7 +4499,20 @@
         }
 
         private void handlePulseWhileDozing(@NonNull PulseCallback callback, int reason) {
-            mDozeScrimController.pulse(callback, reason);
+            mDozeScrimController.pulse(new PulseCallback() {
+
+                @Override
+                public void onPulseStarted() {
+                    callback.onPulseStarted();
+                    mStackScroller.setPulsing(true);
+                }
+
+                @Override
+                public void onPulseFinished() {
+                    callback.onPulseFinished();
+                    mStackScroller.setPulsing(false);
+                }
+            }, reason);
         }
 
         private void handleStopDozing() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index b29c807..8f329c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -83,7 +83,6 @@
     private float mDateScaleFactor;
     private float mGearTranslation;
 
-    private TouchAnimator mAnimator;
     private TouchAnimator mSecondHalfAnimator;
     private TouchAnimator mFirstHalfAnimator;
     private TouchAnimator mDateSizeAnimator;
@@ -154,12 +153,7 @@
         mDateScaleFactor = dateExpandedSize / dateCollapsedSize;
         updateDateTimePosition();
 
-        mAnimator = new TouchAnimator.Builder()
-                .addFloat(mSettingsContainer, "translationY", -mGearTranslation, 0)
-                .addFloat(mMultiUserSwitch, "translationY", -mGearTranslation, 0)
-                .build();
         mSecondHalfAnimator = new TouchAnimator.Builder()
-                .addFloat(mSettingsButton, "rotation", -180, 0)
                 .addFloat(mAlarmStatus, "alpha", 0, 1)
                 .addFloat(mEmergencyOnly, "alpha", 0, 1)
                 .setStartDelay(.5f)
@@ -174,6 +168,9 @@
                 .setStartDelay(.36f)
                 .build();
         mSettingsAlpha = new TouchAnimator.Builder()
+                .addFloat(mSettingsContainer, "translationY", -mGearTranslation, 0)
+                .addFloat(mMultiUserSwitch, "translationY", -mGearTranslation, 0)
+                .addFloat(mSettingsButton, "rotation", -90, 0)
                 .addFloat(mSettingsContainer, "alpha", 0, 1)
                 .addFloat(mMultiUserSwitch, "alpha", 0, 1)
                 .setStartDelay(QSAnimator.EXPANDED_TILE_DELAY)
@@ -211,7 +208,6 @@
     @Override
     public void setExpansion(float headerExpansionFraction) {
         mExpansionAmount = headerExpansionFraction;
-        mAnimator.setPosition(headerExpansionFraction);
         mSecondHalfAnimator.setPosition(headerExpansionFraction);
         mFirstHalfAnimator.setPosition(headerExpansionFraction);
         mDateSizeAnimator.setPosition(headerExpansionFraction);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 2ba1562..117e2b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -227,6 +227,10 @@
         mStatusBarWindowManager.setKeyguardNeedsInput(needsInput);
     }
 
+    public boolean isUnlockWithWallpaper() {
+        return mStatusBarWindowManager.isShowingWallpaper();
+    }
+
     public void setOccluded(boolean occluded) {
         if (occluded && !mOccluded && mShowing) {
             if (mPhoneStatusBar.isInLaunchTransition()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index fcaf050..ada7450 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -100,12 +100,16 @@
 
     private void applyKeyguardFlags(State state) {
         if (state.keyguardShowing) {
-            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
             mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
         } else {
-            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
             mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
         }
+
+        if (state.keyguardShowing && !state.backdropShowing) {
+            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+        } else {
+            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+        }
     }
 
     private void adjustScreenOrientation(State state) {
@@ -173,7 +177,7 @@
     private void applyInputFeatures(State state) {
         if (state.isKeyguardShowingAndNotOccluded()
                 && state.statusBarState == StatusBarState.KEYGUARD
-                && !state.qsExpanded) {
+                && !state.qsExpanded && !state.forceUserActivity) {
             mLpChanged.inputFeatures |=
                     WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
         } else {
@@ -255,6 +259,11 @@
         apply(mCurrentState);
     }
 
+    public void setBackdropShowing(boolean showing) {
+        mCurrentState.backdropShowing = showing;
+        apply(mCurrentState);
+    }
+
     public void setKeyguardFadingAway(boolean keyguardFadingAway) {
         mCurrentState.keyguardFadingAway = keyguardFadingAway;
         apply(mCurrentState);
@@ -265,6 +274,11 @@
         apply(mCurrentState);
     }
 
+    public void setForceUserActivity(boolean forceUserActivity) {
+        mCurrentState.forceUserActivity = forceUserActivity;
+        apply(mCurrentState);
+    }
+
     public void setHeadsUpShowing(boolean showing) {
         mCurrentState.headsUpShowing = showing;
         apply(mCurrentState);
@@ -318,6 +332,10 @@
         pw.println(mCurrentState);
     }
 
+    public boolean isShowingWallpaper() {
+        return !mCurrentState.backdropShowing;
+    }
+
     private static class State {
         boolean keyguardShowing;
         boolean keyguardOccluded;
@@ -332,6 +350,8 @@
         boolean forceStatusBarVisible;
         boolean forceCollapsed;
         boolean forceDozeBrightness;
+        boolean forceUserActivity;
+        boolean backdropShowing;
 
         /**
          * The {@link BaseStatusBar} state from the status bar.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index f03d9e9..c6b1cdf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -69,18 +69,22 @@
 
     @Override
     public void addCallback(Callback callback) {
-        if (callback == null || mCallbacks.contains(callback)) return;
-        if (DEBUG) Log.d(TAG, "addCallback " + callback);
-        mCallbacks.add(callback);
-        mReceiver.setListening(!mCallbacks.isEmpty());
+        synchronized (mCallbacks) {
+            if (callback == null || mCallbacks.contains(callback)) return;
+            if (DEBUG) Log.d(TAG, "addCallback " + callback);
+            mCallbacks.add(callback);
+            mReceiver.setListening(!mCallbacks.isEmpty());
+        }
     }
 
     @Override
     public void removeCallback(Callback callback) {
         if (callback == null) return;
         if (DEBUG) Log.d(TAG, "removeCallback " + callback);
-        mCallbacks.remove(callback);
-        mReceiver.setListening(!mCallbacks.isEmpty());
+        synchronized (mCallbacks) {
+            mCallbacks.remove(callback);
+            mReceiver.setListening(!mCallbacks.isEmpty());
+        }
     }
 
     @Override
@@ -110,8 +114,10 @@
     }
 
     private void fireCallback(boolean isEnabled) {
-        for (Callback callback : mCallbacks) {
-            callback.onHotspotChanged(isEnabled);
+        synchronized (mCallbacks) {
+            for (Callback callback : mCallbacks) {
+                callback.onHotspotChanged(isEnabled);
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index c6659d1..29b0f4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -155,8 +155,21 @@
     }
 
     @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (mEntry.row.isChangingPosition()) {
+            if (getVisibility() == VISIBLE && mEditText.isFocusable()) {
+                mEditText.requestFocus();
+            }
+        }
+    }
+
+    @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
+        if (mEntry.row.isChangingPosition()) {
+            return;
+        }
         mController.removeRemoteInput(mEntry);
     }
 
@@ -229,6 +242,9 @@
         }
 
         private void defocusIfNeeded() {
+            if (mDefocusListener.mEntry.row.isChangingPosition()) {
+                return;
+            }
             if (isFocusable() && isEnabled()) {
                 setInnerFocusable(false);
                 if (mDefocusListener != null) {
@@ -248,9 +264,11 @@
         }
 
         @Override
-        protected void onFocusLost() {
-            super.onFocusLost();
-            defocusIfNeeded();
+        protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+            super.onFocusChanged(focused, direction, previouslyFocusedRect);
+            if (!focused) {
+                defocusIfNeeded();
+            }
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index cedc3c7..ab44b6a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -315,8 +315,8 @@
     public void logoutCurrentUser() {
         int currentUser = ActivityManager.getCurrentUser();
         if (currentUser != UserHandle.USER_SYSTEM) {
-            switchToUserId(UserHandle.USER_SYSTEM);
-            stopUserId(currentUser);
+            pauseRefreshUsers();
+            ActivityManager.logoutCurrentUser();
         }
     }
 
@@ -384,14 +384,6 @@
         }
     }
 
-    private void stopUserId(int id) {
-        try {
-            ActivityManagerNative.getDefault().stopUser(id, /* force= */ false, null);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Couldn't stop user.", e);
-        }
-    }
-
     private void showExitGuestDialog(int id) {
         if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
             mExitGuestDialog.cancel();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index 9d50ab4..676ff2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -96,7 +96,8 @@
                 com.android.internal.R.dimen.notification_content_margin_top);
         mNotificatonTopPadding = getResources().getDimensionPixelSize(
                 R.dimen.notification_children_container_top_padding);
-        mCollapsedBottompadding = 11.5f * getResources().getDisplayMetrics().density;
+        mCollapsedBottompadding = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_margin_bottom);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 824b8b7..59ec6112 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -324,6 +324,7 @@
         }
     };
     private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
+    private boolean mPulsing;
 
     public NotificationStackScrollLayout(Context context) {
         this(context, null);
@@ -371,6 +372,11 @@
     }
 
     @Override
+    public void onSettingsIconRowReset(NotificationSettingsIconRow row) {
+        mSwipeHelper.setSnappedToGear(false);
+    }
+
+    @Override
     protected void onDraw(Canvas canvas) {
         canvas.drawRect(0, mCurrentBounds.top, getWidth(), mCurrentBounds.bottom, mBackgroundPaint);
         if (DEBUG) {
@@ -716,11 +722,15 @@
             mDragAnimPendingChildren.remove(animView);
         }
 
-        if (targetLeft == 0 && mCurrIconRow != null) {
-            mCurrIconRow.resetState();
-            mCurrIconRow = null;
-            if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
-                mGearExposedView = null;
+        if (mCurrIconRow != null) {
+            if (targetLeft == 0) {
+                mCurrIconRow.resetState();
+                mCurrIconRow = null;
+                if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
+                    mGearExposedView = null;
+                }
+            } else {
+                mSwipeHelper.setSnappedToGear(true);
             }
         }
     }
@@ -2194,7 +2204,7 @@
     }
 
     private void updateNotificationAnimationStates() {
-        boolean running = mAnimationsEnabled;
+        boolean running = mAnimationsEnabled || mPulsing;
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             View child = getChildAt(i);
@@ -2204,7 +2214,8 @@
     }
 
     private void updateAnimationState(View child) {
-        updateAnimationState(mAnimationsEnabled && (mIsExpanded || isPinnedHeadsUp(child)), child);
+        updateAnimationState((mAnimationsEnabled || mPulsing)
+                && (mIsExpanded || isPinnedHeadsUp(child)), child);
     }
 
 
@@ -2250,8 +2261,10 @@
         int currentIndex = indexOfChild(child);
         if (child != null && child.getParent() == this && currentIndex != newIndex) {
             mChangePositionInProgress = true;
+            ((ExpandableView)child).setChangingPosition(true);
             removeView(child);
             addView(child, newIndex);
+            ((ExpandableView)child).setChangingPosition(false);
             mChangePositionInProgress = false;
             if (mIsExpanded && mAnimationsEnabled && child.getVisibility() != View.GONE) {
                 mChildrenChangingPositions.add(child);
@@ -2652,6 +2665,7 @@
         mIsExpansionChanging = false;
         if (!mIsExpanded) {
             mOwnScrollY = 0;
+            mPhoneStatusBar.resetUserExpandedStates();
 
             // lets make sure nothing is in the overlay anymore
             getOverlay().clear();
@@ -2677,6 +2691,16 @@
         if (changed) {
             if (!mIsExpanded) {
                 mGroupManager.collapseAllGroups();
+            } else {
+                // XXX: HACK: we should not be clearing notification effects from way down here.
+                // But at the moment we don't have a reliable way to know when the window is
+                // actually exposed to the air, so
+                if (mPhoneStatusBar.getBarState() != StatusBarState.KEYGUARD) {
+                    if (DEBUG) {
+                        Log.v(TAG, "clearing notification effects from scroller");
+                    }
+                    mPhoneStatusBar.clearNotificationEffects();
+                }
             }
             updateNotificationAnimationStates();
             updateChronometers();
@@ -2725,13 +2749,13 @@
         if (view instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) view;
             if (row.isUserLocked() && row != getFirstChildNotGone()) {
+                if (row.isSummaryWithChildren()) {
+                    return;
+                }
                 // We are actually expanding this view
-                float endPosition;
+                float endPosition = row.getTranslationY() + row.getActualHeight();
                 if (row.isChildInGroup()) {
-                    ExpandableNotificationRow parent = row.getNotificationParent();
-                    endPosition = parent.getTranslationY() + parent.getActualHeight();
-                } else {
-                    endPosition = row.getTranslationY() + row.getActualHeight();
+                    endPosition += row.getNotificationParent().getTranslationY();
                 }
                 int stackEnd = mMaxLayoutHeight - mBottomStackPeekSize -
                         mBottomStackSlowDownHeight + (int) mStackTranslation;
@@ -3322,6 +3346,11 @@
         return mIsExpanded;
     }
 
+    public void setPulsing(boolean pulsing) {
+        mPulsing = pulsing;
+        updateNotificationAnimationStates();
+    }
+
     /**
      * A listener that is notified when some child locations might have changed.
      */
@@ -3369,15 +3398,11 @@
     }
 
     private class NotificationSwipeHelper extends SwipeHelper {
-        private static final int MOVE_STATE_LEFT = -1;
-        private static final int MOVE_STATE_UNDEFINED = 0;
-        private static final int MOVE_STATE_RIGHT = 1;
-
         private static final long GEAR_SHOW_DELAY = 60;
-
         private CheckForDrag mCheckForDrag;
         private Handler mHandler;
-        private int mMoveState = MOVE_STATE_UNDEFINED;
+        private boolean mGearSnappedTo;
+        private boolean mGearSnappedOnLeft;
 
         public NotificationSwipeHelper(int swipeDirection, Callback callback, Context context) {
             super(swipeDirection, callback, context);
@@ -3390,6 +3415,10 @@
             mTranslatingParentView = currView;
 
             // Reset check for drag gesture
+            cancelCheckForDrag();
+            if (mCurrIconRow != null) {
+                mCurrIconRow.setSnapping(false);
+            }
             mCheckForDrag = null;
             mCurrIconRow = null;
 
@@ -3401,17 +3430,32 @@
                 mCurrIconRow = ((ExpandableNotificationRow) currView).getSettingsRow();
                 mCurrIconRow.setGearListener(NotificationStackScrollLayout.this);
             }
-            mMoveState = MOVE_STATE_UNDEFINED;
         }
 
         @Override
         public void onMoveUpdate(View view, float translation, float delta) {
-            final int newMoveState = (delta < 0) ? MOVE_STATE_RIGHT : MOVE_STATE_LEFT;
-            if (mMoveState != MOVE_STATE_UNDEFINED && mMoveState != newMoveState) {
-                // Changed directions, make sure we check for drag again.
-                mCheckForDrag = null;
+            if (mCurrIconRow != null) {
+                mCurrIconRow.setSnapping(false); // If we're moving, we're not snapping.
+
+                // If the gear is visible and the movement is towards it it's not a location change.
+                boolean onLeft = mGearSnappedTo ? mGearSnappedOnLeft : mCurrIconRow.isIconOnLeft();
+                boolean locationChange = isTowardsGear(translation, onLeft)
+                        ? false : mCurrIconRow.isIconLocationChange(translation);
+                if (locationChange) {
+                    // Don't consider it "snapped" if location has changed.
+                    setSnappedToGear(false);
+
+                    // Changed directions, make sure we check to fade in icon again.
+                    if (!mHandler.hasCallbacks(mCheckForDrag)) {
+                        // No check scheduled, set null to schedule a new one.
+                        mCheckForDrag = null;
+                    } else {
+                        // Check scheduled, reset alpha and update location; check will fade it in
+                        mCurrIconRow.setGearAlpha(0f);
+                        mCurrIconRow.setIconLocation(translation > 0 /* onLeft */);
+                    }
+                }
             }
-            mMoveState = newMoveState;
 
             final boolean gutsExposed = (view instanceof ExpandableNotificationRow)
                     && ((ExpandableNotificationRow) view).areGutsExposed();
@@ -3424,35 +3468,101 @@
 
         @Override
         public void dismissChild(final View view, float velocity) {
-            cancelCheckForDrag();
             super.dismissChild(view, velocity);
+            cancelCheckForDrag();
+            setSnappedToGear(false);
         }
 
         @Override
         public void snapChild(final View animView, final float targetLeft, float velocity) {
+            super.snapChild(animView, targetLeft, velocity);
+            onDragCancelled(animView);
+            if (targetLeft == 0) {
+                cancelCheckForDrag();
+                setSnappedToGear(false);
+            }
+        }
+
+
+        @Override
+        public boolean handleUpEvent(MotionEvent ev, View animView, float velocity,
+                float translation) {
+            if (mCurrIconRow == null) {
+                cancelCheckForDrag();
+                return false; // Let SwipeHelper handle it.
+            }
+
+            boolean gestureTowardsGear = isTowardsGear(velocity, mCurrIconRow.isIconOnLeft());
+            boolean gestureFastEnough = Math.abs(velocity) > getEscapeVelocity();
+
+            if (mGearSnappedTo && mCurrIconRow.isVisible()) {
+                if (mGearSnappedOnLeft == mCurrIconRow.isIconOnLeft()) {
+                    boolean coveringGear =
+                            Math.abs(getTranslation(animView)) <= getSpaceForGear(animView) * 0.6f;
+                    if (gestureTowardsGear || coveringGear) {
+                        // Gesture is towards or covering the gear
+                        snapChild(animView, 0 /* leftTarget */, velocity);
+                    } else if (isDismissGesture(ev)) {
+                        // Gesture is a dismiss that's not towards the gear
+                        dismissChild(animView, swipedFastEnough() ? velocity : 0f);
+                    } else {
+                        // Didn't move enough to dismiss or cover, snap to the gear
+                        snapToGear(animView, velocity);
+                    }
+                } else if ((!gestureFastEnough && swipedEnoughToShowGear(animView))
+                        || (gestureTowardsGear && !swipedFarEnough())) {
+                    // The gear has been snapped to previously, however, the gear is now on the
+                    // other side. If gesture is towards gear and not too far snap to the gear.
+                    snapToGear(animView, velocity);
+                } else {
+                    dismissOrSnapBack(animView, velocity, ev);
+                }
+            } else if ((!gestureFastEnough && swipedEnoughToShowGear(animView))
+                    || gestureTowardsGear) {
+                // Gear has not been snapped to previously and this is gear revealing gesture
+                snapToGear(animView, velocity);
+            } else {
+                dismissOrSnapBack(animView, velocity, ev);
+            }
+            return true;
+        }
+
+        private void dismissOrSnapBack(View animView, float velocity, MotionEvent ev) {
+            if (isDismissGesture(ev)) {
+                dismissChild(animView, swipedFastEnough() ? velocity : 0f);
+            } else {
+                snapChild(animView, 0 /* leftTarget */, velocity);
+            }
+        }
+
+        private void snapToGear(View animView, float velocity) {
+            final float snapBackThreshold = getSpaceForGear(animView);
+            final float target = mCurrIconRow.isIconOnLeft() ? snapBackThreshold
+                    : -snapBackThreshold;
+            mGearExposedView = mTranslatingParentView;
+            if (mGearDisplayedListener != null
+                    && (animView instanceof ExpandableNotificationRow)) {
+                mGearDisplayedListener.onGearDisplayed((ExpandableNotificationRow) animView);
+            }
+            if (mCurrIconRow != null) {
+                mCurrIconRow.setSnapping(true);
+                setSnappedToGear(true);
+            }
+            onDragCancelled(animView);
+            super.snapChild(animView, target, velocity);
+        }
+
+        private boolean swipedEnoughToShowGear(View animView) {
             final float snapBackThreshold = getSpaceForGear(animView);
             final float translation = getTranslation(animView);
             final boolean fromLeft = translation > 0;
             final float absTrans = Math.abs(translation);
             final float notiThreshold = getSize(mTranslatingParentView) * 0.4f;
 
-            boolean pastGear = (fromLeft && translation >= snapBackThreshold * 0.4f
-                    && translation <= notiThreshold) ||
-                    (!fromLeft && absTrans >= snapBackThreshold * 0.4f
-                            && absTrans <= notiThreshold);
-
-            if (pastGear && !isPinnedHeadsUp(animView)
-                    && (animView instanceof ExpandableNotificationRow)) {
-                // bouncity
-                final float target = fromLeft ? snapBackThreshold : -snapBackThreshold;
-                mGearExposedView = mTranslatingParentView;
-                if (mGearDisplayedListener != null) {
-                    mGearDisplayedListener.onGearDisplayed((ExpandableNotificationRow) animView);
-                }
-                super.snapChild(animView, target, velocity);
-            } else {
-                super.snapChild(animView, 0, velocity);
-            }
+            // If the notification can't be dismissed then how far it can move is
+            // restricted -- reduce the distance it needs to move in this case.
+            final float multiplier = canChildBeDismissed(animView) ? 0.4f : 0.2f;
+            return absTrans >= snapBackThreshold * 0.4f && absTrans <= notiThreshold;
         }
 
         @Override
@@ -3489,6 +3599,25 @@
         }
 
         /**
+         * Returns whether the gesture is towards the gear location or not.
+         */
+        private boolean isTowardsGear(float velocity, boolean onLeft) {
+            if (mCurrIconRow == null) {
+                return false;
+            }
+            return mCurrIconRow.isVisible()
+                    && ((onLeft && velocity <= 0) || (!onLeft && velocity >= 0));
+        }
+
+        /**
+         * Indicates the the gear has been snapped to.
+         */
+        private void setSnappedToGear(boolean snapped) {
+            mGearSnappedOnLeft = (mCurrIconRow != null) ? mCurrIconRow.isIconOnLeft() : false;
+            mGearSnappedTo = snapped && mCurrIconRow != null;
+        }
+
+        /**
          * Returns the horizontal space in pixels required to display the gear behind a
          * notification.
          */
@@ -3500,7 +3629,7 @@
         }
 
         private void checkForDrag() {
-            if (mCheckForDrag == null) {
+            if (mCheckForDrag == null || !mHandler.hasCallbacks(mCheckForDrag)) {
                 mCheckForDrag = new CheckForDrag();
                 mHandler.postDelayed(mCheckForDrag, GEAR_SHOW_DELAY);
             }
@@ -3511,7 +3640,6 @@
                 mCurrIconRow.cancelFadeAnimator();
             }
             mHandler.removeCallbacks(mCheckForDrag);
-            mCheckForDrag = null;
         }
 
         private final class CheckForDrag implements Runnable {
@@ -3521,14 +3649,13 @@
                 final float absTransX = Math.abs(translation);
                 final float bounceBackToGearWidth = getSpaceForGear(mTranslatingParentView);
                 final float notiThreshold = getSize(mTranslatingParentView) * 0.4f;
-                if (mCurrIconRow != null && absTransX >= bounceBackToGearWidth * 0.4
+                if ((mCurrIconRow != null && (!mCurrIconRow.isVisible()
+                        || mCurrIconRow.isIconLocationChange(translation)))
+                        && absTransX >= bounceBackToGearWidth * 0.4
                         && absTransX < notiThreshold) {
-                    // Show icon
+                    // Fade in the gear
                     mCurrIconRow.fadeInSettings(translation > 0 /* fromLeft */, translation,
                             notiThreshold);
-                } else {
-                    // Allow more to be posted if this wasn't a drag.
-                    mCheckForDrag = null;
                 }
             }
         }
@@ -3541,7 +3668,7 @@
 
             final View prevGearExposedView = mGearExposedView;
             mGearExposedView = null;
-
+            mGearSnappedTo = false;
             Animator anim = getViewTranslationAnimator(prevGearExposedView,
                     0 /* leftTarget */, null /* updateListener */);
             if (anim != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
index ea15b81..ff7ea27 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -68,6 +68,9 @@
 
     public static final int SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH = 0x1;
     public static final int SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_OVERLAY_ACTIVITY_FINISH = 0x2;
+
+    private static final int CLOSE_PIP_WHEN_MEDIA_SESSION_GONE_TIMEOUT_MS = 3000;
+
     private int mSuspendPipResizingReason;
 
     private static final float SCALE_FACTOR = 1.1f;
@@ -172,6 +175,12 @@
             resizePinnedStack(mState);
         }
     };
+    private final Runnable mClosePipRunnable = new Runnable() {
+        @Override
+        public void run() {
+            closePip();
+        }
+    };
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -283,6 +292,7 @@
         for (int i = mListeners.size() - 1; i >= 0; --i) {
             mListeners.get(i).onPipActivityClosed();
         }
+        mHandler.removeCallbacks(mClosePipRunnable);
     }
 
     /**
@@ -545,6 +555,12 @@
             for (int i = mListeners.size() - 1; i >= 0; i--) {
                 mListeners.get(i).onMediaControllerChanged();
             }
+            if (mPipMediaController == null) {
+                mHandler.postDelayed(mClosePipRunnable,
+                        CLOSE_PIP_WHEN_MEDIA_SESSION_GONE_TIMEOUT_MS);
+            } else {
+                mHandler.removeCallbacks(mClosePipRunnable);
+            }
         }
     }
 
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index fb50df9..d929519 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -1993,6 +1993,25 @@
     // Settings -> Apps -> Gear -> Special access
     SPECIAL_ACCESS = 351;
 
+    // Logs that the user docks window via shortcut key.
+    WINDOW_DOCK_SHORTCUTS = 352;
+
+    // User already denied access to the request folder; action takes an integer
+    // representing the folder's index on Environment.STANDARD_DIRECTORIES
+    ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_FOLDER = 353;
+
+    // User already denied access to the request folder; action pass package name
+    // of calling package.
+    ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_PACKAGE = 354;
+
+    // User denied access to the request folder and checked 'Do not ask again';
+    // action takes an integer representing the folder's index on Environment.STANDARD_DIRECTORIES
+    ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_FOLDER = 355;
+
+    // User denied access to the request folder and checked 'Do not ask again';
+    // action pass package name of calling package.
+    ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_PACKAGE = 356;
+
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
   }
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 4e667c6..e0f5934 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -2071,6 +2071,8 @@
         sc.array4End = 0;
 
         sca = &sc;
+        // sc_size is required, but unused, by the runtime and drivers.
+        sc_size = sizeof(sc);
     }
 
     rsScriptForEachMulti((RsContext)con, (RsScript)script, slot,
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
index 284c309..562d950 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java
@@ -37,7 +37,8 @@
 
 /**
  * This class handles gesture detection for the Touch Explorer.  It collects
- * touch events, and sends events to mListener as gestures are recognized.
+ * touch events and determines when they match a gesture, as well as when they
+ * won't match a gesture.  These state changes are then surfaced to mListener.
  */
 class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListener {
 
@@ -46,12 +47,58 @@
     // Tag for logging received events.
     private static final String LOG_TAG = "AccessibilityGestureDetector";
 
+    /**
+     * Listener functions are called as a result of onMoveEvent().  The current
+     * MotionEvent in the context of these functions is the event passed into
+     * onMotionEvent.
+     */
     public interface Listener {
-        public void onDoubleTapAndHold(MotionEvent event, int policyFlags);
-        public boolean onDoubleTap(MotionEvent event, int policyFlags);
-        public boolean onGestureCompleted(int gestureId);
-        public void onGestureStarted();
-        public void onGestureCancelled(MotionEvent event, int policyFlags);
+        /**
+         * Called when the user has performed a double tap and then held down
+         * the second tap.
+         *
+         * @param event The most recent MotionEvent received.
+         * @param policyFlags The policy flags of the most recent event.
+         */
+        void onDoubleTapAndHold(MotionEvent event, int policyFlags);
+
+        /**
+         * Called when the user lifts their finger on the second tap of a double
+         * tap.
+         *
+         * @param event The most recent MotionEvent received.
+         * @param policyFlags The policy flags of the most recent event.
+         *
+         * @return true if the event is consumed, else false
+         */
+        boolean onDoubleTap(MotionEvent event, int policyFlags);
+
+        /**
+         * Called when the system has decided the event stream is a gesture.
+         *
+         * @return true if the event is consumed, else false
+         */
+        boolean onGestureStarted();
+
+        /**
+         * Called when an event stream is recognized as a gesture.
+         *
+         * @param gestureId ID of the gesture that was recognized.
+         *
+         * @return true if the event is consumed, else false
+         */
+        boolean onGestureCompleted(int gestureId);
+
+        /**
+         * Called when the system has decided an event stream doesn't match any
+         * known gesture.
+         *
+         * @param event The most recent MotionEvent received.
+         * @param policyFlags The policy flags of the most recent event.
+         *
+         * @return true if the event is consumed, else false
+         */
+        public boolean onGestureCancelled(MotionEvent event, int policyFlags);
     }
 
     private final Listener mListener;
@@ -145,6 +192,18 @@
                 context.getResources().getDisplayMetrics()) * GESTURE_CONFIRM_MM;
     }
 
+    /**
+     * Handle a motion event.  If an action is completed, the appropriate
+     * callback on mListener is called, and the return value of the callback is
+     * passed to the caller.
+     *
+     * @param event The raw motion event.  It's important that this be the raw
+     * event, before any transformations have been applied, so that measurements
+     * can be made in physical units.
+     * @param policyFlags Policy flags for the event.
+     *
+     * @return true if the event is consumed, else false
+     */
     public boolean onMotionEvent(MotionEvent event, int policyFlags) {
         final float x = event.getX();
         final float y = event.getY();
@@ -179,13 +238,20 @@
                         mBaseY = y;
                         mBaseTime = time;
 
+                        // Since the pointer has moved, this is not a double
+                        // tap.
+                        mFirstTapDetected = false;
+                        mDoubleTapDetected = false;
+
                         // If this hasn't been confirmed as a gesture yet, send
                         // the event.
                         if (!mGestureStarted) {
                             mGestureStarted = true;
-                            mListener.onGestureStarted();
+                            return mListener.onGestureStarted();
                         }
-                    } else {
+                    } else if (!mFirstTapDetected) {
+                        // The finger may not move if they are double tapping.
+                        // In that case, we shouldn't cancel the gesture.
                         final long timeDelta = time - mBaseTime;
                         final long threshold = mGestureStarted ?
                             CANCEL_ON_PAUSE_THRESHOLD_STARTED_MS :
@@ -195,8 +261,7 @@
                         // timeout, cancel gesture detection.
                         if (timeDelta > threshold) {
                             cancelGesture();
-                            mListener.onGestureCancelled(event, policyFlags);
-                            return false;
+                            return mListener.onGestureCancelled(event, policyFlags);
                         }
                     }
 
@@ -211,16 +276,13 @@
                 break;
 
             case MotionEvent.ACTION_UP:
-                if (maybeFinishDoubleTap(event, policyFlags)) {
-                    return true;
+                if (mDoubleTapDetected) {
+                    return finishDoubleTap(event, policyFlags);
                 }
                 if (mGestureStarted) {
                     mStrokeBuffer.add(new GesturePoint(x, y, time));
 
-                    if (!recognizeGesture()) {
-                        mListener.onGestureCancelled(event, policyFlags);
-                    }
-                    return true;
+                    return recognizeGesture(event, policyFlags);
                 }
                 break;
 
@@ -244,8 +306,8 @@
             case MotionEvent.ACTION_POINTER_UP:
                 // If we're detecting taps on the second finger, see if we
                 // should finish the double tap.
-                if (mSecondFingerDoubleTap && maybeFinishDoubleTap(event, policyFlags)) {
-                    return true;
+                if (mSecondFingerDoubleTap && mDoubleTapDetected) {
+                    return finishDoubleTap(event, policyFlags);
                 }
                 break;
 
@@ -308,7 +370,7 @@
         // The processing of the double tap is deferred until the finger is
         // lifted, so that we can detect a long press on the second tap.
         mDoubleTapDetected = true;
-        return true;
+        return false;
     }
 
     private void maybeSendLongPress(MotionEvent event, int policyFlags) {
@@ -321,11 +383,7 @@
         mListener.onDoubleTapAndHold(event, policyFlags);
     }
 
-    private boolean maybeFinishDoubleTap(MotionEvent event, int policyFlags) {
-        if (!mDoubleTapDetected) {
-            return false;
-        }
-
+    private boolean finishDoubleTap(MotionEvent event, int policyFlags) {
         clear();
 
         return mListener.onDoubleTap(event, policyFlags);
@@ -337,7 +395,7 @@
         mStrokeBuffer.clear();
     }
 
-    private boolean recognizeGesture() {
+    private boolean recognizeGesture(MotionEvent event, int policyFlags) {
         Gesture gesture = new Gesture();
         gesture.addStroke(new GestureStroke(mStrokeBuffer));
 
@@ -351,16 +409,14 @@
                 }
                 try {
                     final int gestureId = Integer.parseInt(bestPrediction.name);
-                    if (mListener.onGestureCompleted(gestureId)) {
-                        return true;
-                    }
+                    return mListener.onGestureCompleted(gestureId);
                 } catch (NumberFormatException nfe) {
                     Slog.w(LOG_TAG, "Non numeric gesture id:" + bestPrediction.name);
                 }
             }
         }
 
-        return false;
+        return mListener.onGestureCancelled(event, policyFlags);
     }
 
     private MotionEvent mapSecondPointerToFirstPointer(MotionEvent event) {
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index 3ecff40..3cc991c 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -437,6 +437,20 @@
     }
 
     @Override
+    public boolean onGestureStarted() {
+      // We have to perform gesture detection, so
+      // clear the current state and try to detect.
+      mCurrentState = STATE_GESTURE_DETECTING;
+      mSendHoverEnterAndMoveDelayed.cancel();
+      mSendHoverExitDelayed.cancel();
+      mExitGestureDetectionModeDelayed.post();
+      // Send accessibility event to announce the start
+      // of gesture recognition.
+      sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_START);
+      return false;
+    }
+
+    @Override
     public boolean onGestureCompleted(int gestureId) {
         if (mCurrentState != STATE_GESTURE_DETECTING) {
             return false;
@@ -450,36 +464,26 @@
     }
 
     @Override
-    public void onGestureStarted() {
-      // We have to perform gesture detection, so
-      // clear the current state and try to detect.
-      mCurrentState = STATE_GESTURE_DETECTING;
-      mSendHoverEnterAndMoveDelayed.cancel();
-      mSendHoverExitDelayed.cancel();
-      mExitGestureDetectionModeDelayed.post();
-      // Send accessibility event to announce the start
-      // of gesture recognition.
-      sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_START);
-    }
+    public boolean onGestureCancelled(MotionEvent event, int policyFlags) {
+        if (mCurrentState == STATE_GESTURE_DETECTING) {
+            endGestureDetection();
+            return true;
+        } else if (mCurrentState == STATE_TOUCH_EXPLORING) {
+            // If the finger is still moving, pass the event on.
+            if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
+                final int pointerId = mReceivedPointerTracker.getPrimaryPointerId();
+                final int pointerIdBits = (1 << pointerId);
 
-    @Override
-    public void onGestureCancelled(MotionEvent event, int policyFlags) {
-      if (mCurrentState == STATE_GESTURE_DETECTING) {
-          endGestureDetection();
-      } else if (mCurrentState == STATE_TOUCH_EXPLORING) {
-          // If the finger is still moving, pass the event on.
-          if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
-              final int pointerId = mReceivedPointerTracker.getPrimaryPointerId();
-              final int pointerIdBits = (1 << pointerId);
-
-              // We have just decided that the user is touch,
-              // exploring so start sending events.
-              mSendHoverEnterAndMoveDelayed.addEvent(event);
-              mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
-              mSendHoverExitDelayed.cancel();
-              sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags);
-          }
-      }
+                // We have just decided that the user is touch,
+                // exploring so start sending events.
+                mSendHoverEnterAndMoveDelayed.addEvent(event);
+                mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
+                mSendHoverExitDelayed.cancel();
+                sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags);
+                return true;
+            }
+        }
+        return false;
     }
 
     /**
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 3659a40..a4f85db 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -210,6 +210,7 @@
     private final UserManager mUserManager;
     private final AppOpsManager mAppOpsManager;
     private final KeyguardManager mKeyguardManager;
+    private final DevicePolicyManagerInternal mDevicePolicyManagerInternal;
 
     private final SecurityPolicy mSecurityPolicy;
 
@@ -232,6 +233,7 @@
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
         mKeyguardManager = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE);
+        mDevicePolicyManagerInternal = LocalServices.getService(DevicePolicyManagerInternal.class);
         mSaveStateHandler = BackgroundThread.getHandler();
         mCallbackHandler = new CallbackHandler(mContext.getMainLooper());
         mBackupRestoreController = new BackupRestoreController();
@@ -298,11 +300,9 @@
     }
 
     private void registerOnCrossProfileProvidersChangedListener() {
-        DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService(
-                DevicePolicyManagerInternal.class);
         // The device policy is an optional component.
-        if (devicePolicyManager != null) {
-            devicePolicyManager.addOnCrossProfileWidgetProvidersChangeListener(this);
+        if (mDevicePolicyManagerInternal != null) {
+            mDevicePolicyManagerInternal.addOnCrossProfileWidgetProvidersChangeListener(this);
         }
     }
 
@@ -588,7 +588,7 @@
             try {
                 UserInfo userInfo = mUserManager.getUserInfo(providerUserId);
                 showBadge = userInfo.isManagedProfile();
-                onClickIntent = UnlaunchableAppActivity.createPackageSuspendedDialogIntent(
+                onClickIntent = mDevicePolicyManagerInternal.createPackageSuspendedDialogIntent(
                         providerPackage, providerUserId);
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -3574,15 +3574,12 @@
         }
 
         public boolean isProviderWhiteListed(String packageName, int profileId) {
-            DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService(
-                    DevicePolicyManagerInternal.class);
-
             // If the policy manager is not available on the device we deny it all.
-            if (devicePolicyManager == null) {
+            if (mDevicePolicyManagerInternal == null) {
                 return false;
             }
 
-            List<String> crossProfilePackages = devicePolicyManager
+            List<String> crossProfilePackages = mDevicePolicyManagerInternal
                     .getCrossProfileWidgetProviders(profileId);
 
             return crossProfilePackages.contains(packageName);
diff --git a/services/core/Android.mk b/services/core/Android.mk
index aaa2211..99c5dd6 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -7,7 +7,8 @@
 LOCAL_SRC_FILES += \
     $(call all-java-files-under,java) \
     java/com/android/server/EventLogTags.logtags \
-    java/com/android/server/am/EventLogTags.logtags
+    java/com/android/server/am/EventLogTags.logtags \
+    ../../../../system/netd/server/binder/android/net/INetd.aidl
 
 LOCAL_JAVA_LIBRARIES := services.net telephony-common
 LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 4667172..c5a210c 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -150,6 +150,12 @@
     int mNumTimeChanged;
 
     /**
+     * The current set of user whitelisted apps for device idle mode, meaning these are allowed
+     * to freely schedule alarms.
+     */
+    int[] mDeviceIdleUserWhitelist = new int[0];
+
+    /**
      * For each uid, this is the last time we dispatched an "allow while idle" alarm,
      * used to determine the earliest we can dispatch the next such alarm.
      */
@@ -936,6 +942,7 @@
         }
 
         publishBinderService(Context.ALARM_SERVICE, mService);
+        publishLocalService(LocalService.class, new LocalService());
     }
 
     @Override
@@ -1251,14 +1258,6 @@
                 flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
             }
 
-            // If the caller is a core system component, and not calling to do work on behalf
-            // of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.  This means we
-            // will allow these alarms to go off as normal even while idle, with no timing
-            // restrictions.
-            if (callingUid < Process.FIRST_APPLICATION_UID && workSource == null) {
-                flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
-            }
-
             // If this is an exact time alarm, then it can't be batched with other alarms.
             if (windowLength == AlarmManager.WINDOW_EXACT) {
                 flags |= AlarmManager.FLAG_STANDALONE;
@@ -1268,6 +1267,16 @@
             // use it to wake early from idle if needed.
             if (alarmClock != null) {
                 flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
+
+            // If the caller is a core system component or on the user's whitelist, and not calling
+            // to do work on behalf of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.
+            // This means we will allow these alarms to go off as normal even while idle, with no
+            // timing restrictions.
+            } else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
+                    || Arrays.binarySearch(mDeviceIdleUserWhitelist,
+                            UserHandle.getAppId(callingUid)) >= 0)) {
+                flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
+                flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
             }
 
             setImpl(type, triggerAtTime, windowLength, interval, operation, directReceiver,
@@ -1344,6 +1353,12 @@
         }
     };
 
+    public final class LocalService {
+        public void setDeviceIdleUserWhitelist(int[] appids) {
+            setDeviceIdleUserWhitelistImpl(appids);
+        }
+    }
+
     void dumpImpl(PrintWriter pw) {
         synchronized (mLock) {
             pw.println("Current Alarm Manager state:");
@@ -1386,6 +1401,7 @@
             pw.print("  Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
                     pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
             pw.print("  Num time change events: "); pw.println(mNumTimeChanged);
+            pw.println("  mDeviceIdleUserWhitelist=" + Arrays.toString(mDeviceIdleUserWhitelist));
 
             pw.println();
             pw.println("  Next alarm clock information: ");
@@ -1678,6 +1694,12 @@
         }
     }
 
+    void setDeviceIdleUserWhitelistImpl(int[] appids) {
+        synchronized (mLock) {
+            mDeviceIdleUserWhitelist = appids;
+        }
+    }
+
     AlarmManager.AlarmClockInfo getNextAlarmClockImpl(int userId) {
         synchronized (mLock) {
             return mNextAlarmClockForUser.get(userId);
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 32f2d59..e7db2a8 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -25,6 +25,7 @@
 import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -57,6 +58,7 @@
 import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.Log;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
@@ -107,8 +109,23 @@
 
     private final SparseArray<UidState> mUidStates = new SparseArray<>();
 
-    /** These are app op restrictions imposed per user from various parties */
-    private final ArrayMap<IBinder, SparseArray<boolean[]>> mOpUserRestrictions = new ArrayMap<>();
+    /*
+     * These are app op restrictions imposed per user from various parties.
+     *
+     * This is organized as follows:
+     *
+     * ArrayMap w/ mapping:
+     *  IBinder (for client imposing restriction) --> SparseArray w/ mapping:
+     *    User handle --> Pair containing:
+     *       - Array w/ index = AppOp code, value = restricted status boolean
+     *       - SparseArray w/ mapping:
+     *          AppOp code --> Set of packages that are not restricted for this code
+     *
+     * For efficiency, a core assumption here is that the number of per-package exemptions stored
+     * here will be relatively small.  If this changes, this data structure should be revisited.
+     */
+    private final ArrayMap<IBinder, SparseArray<Pair<boolean[], SparseArray<ArraySet<String>>>>>
+            mOpUserRestrictions = new ArrayMap<>();
 
     private static final class UidState {
         public final int uid;
@@ -1267,11 +1284,38 @@
     private boolean isOpRestricted(int uid, int code, String packageName) {
         int userHandle = UserHandle.getUserId(uid);
         final int restrictionSetCount = mOpUserRestrictions.size();
+
         for (int i = 0; i < restrictionSetCount; i++) {
-            SparseArray<boolean[]> perUserRestrictions = mOpUserRestrictions.valueAt(i);
-            boolean[] opRestrictions = perUserRestrictions.get(userHandle);
-            if (opRestrictions != null && opRestrictions[code]) {
+            // For each client, check that the given op is not restricted, or that the given
+            // package is exempt from the restriction.
+
+            SparseArray<Pair<boolean[],SparseArray<ArraySet<String>>>> perUserRestrictions =
+                    mOpUserRestrictions.valueAt(i);
+
+            Pair<boolean[],SparseArray<ArraySet<String>>> restrictions =
+                    perUserRestrictions.get(userHandle);
+            if (restrictions == null) {
+                continue; // No restrictions set by this client
+            }
+
+            boolean[] opRestrictions = restrictions.first;
+            SparseArray<ArraySet<String>> opExceptions = restrictions.second;
+
+            if (opRestrictions == null) {
+                continue; // No restrictions set by this client
+            }
+
+            if (opRestrictions[code]) {
+
+                if (opExceptions != null) {
+                    ArraySet<String> ex = opExceptions.get(code);
+                    if (ex != null && ex.contains(packageName)) {
+                        continue; // AppOps code is restricted, but this package is exempt
+                    }
+                }
+
                 if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
+                    // If we are the system, bypass user restrictions for certain codes
                     synchronized (this) {
                         Ops ops = getOpsLocked(uid, packageName, true);
                         if ((ops != null) && ops.isPrivileged) {
@@ -1279,6 +1323,7 @@
                         }
                     }
                 }
+
                 return true;
             }
         }
@@ -2069,7 +2114,8 @@
     }
 
     @Override
-    public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle) {
+    public void setUserRestriction(int code, boolean restricted, IBinder token, int userHandle,
+            String[] exceptionPackages) {
         if (Binder.getCallingPid() != Process.myPid()) {
             mContext.enforcePermission(Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS,
                     Binder.getCallingPid(), Binder.getCallingUid(), null);
@@ -2085,12 +2131,40 @@
         }
         verifyIncomingOp(code);
         Preconditions.checkNotNull(token);
-        setUserRestrictionNoCheck(code, restricted, token, userHandle);
+        setUserRestrictionNoCheck(code, restricted, token, userHandle, exceptionPackages);
     }
 
     private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token,
             int userHandle) {
+        setUserRestrictionNoCheck(code, restricted, token, userHandle, /*exceptionPackages*/null);
+    }
+
+    private void setUserRestrictionNoCheck(int code, boolean restricted, IBinder token,
+            int userHandle, String[] exceptionPackages) {
+
         final boolean[] opRestrictions = getOrCreateUserRestrictionsForToken(token, userHandle);
+
+        if (restricted) {
+            final SparseArray<ArraySet<String>> opExceptions =
+                    getUserPackageExemptionsForToken(token, userHandle);
+
+            ArraySet<String> exceptions = opExceptions.get(code);
+            if (exceptionPackages != null && exceptionPackages.length > 0) {
+                if (exceptions == null) {
+                    exceptions = new ArraySet<>(exceptionPackages.length);
+                    opExceptions.put(code, exceptions);
+                } else {
+                    exceptions.clear();
+                }
+
+                for (String p : exceptionPackages) {
+                    exceptions.add(p);
+                }
+            } else {
+                opExceptions.remove(code);
+            }
+        }
+
         if (opRestrictions[code] == restricted) {
             return;
         }
@@ -2132,7 +2206,8 @@
         checkSystemUid("removeUser");
         final int tokenCount = mOpUserRestrictions.size();
         for (int i = tokenCount - 1; i >= 0; i--) {
-            SparseArray<boolean[]> opRestrictions = mOpUserRestrictions.valueAt(i);
+            SparseArray<Pair<boolean[], SparseArray<ArraySet<String>>>> opRestrictions =
+                    mOpUserRestrictions.valueAt(i);
             if (opRestrictions != null) {
                 opRestrictions.remove(userHandle);
                 if (opRestrictions.size() <= 0) {
@@ -2144,15 +2219,32 @@
 
 
     private void pruneUserRestrictionsForToken(IBinder token, int userHandle) {
-        SparseArray<boolean[]> perTokenRestrictions = mOpUserRestrictions.get(token);
+        SparseArray<Pair<boolean[], SparseArray<ArraySet<String>>>> perTokenRestrictions =
+                mOpUserRestrictions.get(token);
         if (perTokenRestrictions != null) {
-            final boolean[] opRestrictions = perTokenRestrictions.get(userHandle);
-            if (opRestrictions != null) {
-                for (boolean restriction : opRestrictions) {
-                    if (restriction) {
-                        return;
+            final Pair<boolean[], SparseArray<ArraySet<String>>> restrictions =
+                    perTokenRestrictions.get(userHandle);
+
+            if (restrictions != null) {
+                final boolean[] opRestrictions = restrictions.first;
+                final SparseArray<ArraySet<String>> opExceptions = restrictions.second;
+                boolean stillHasRestrictions = false;
+                if (opRestrictions != null) {
+                    for (int i = 0; i < opRestrictions.length; i++) {
+                        boolean restriction = opRestrictions[i];
+                        if (restriction) {
+                            stillHasRestrictions = true;
+                        } else {
+                            opExceptions.remove(i);
+                        }
                     }
                 }
+
+                if (stillHasRestrictions) {
+                    return;
+                }
+
+                // No restrictions set for this client
                 perTokenRestrictions.remove(userHandle);
                 if (perTokenRestrictions.size() <= 0) {
                     mOpUserRestrictions.remove(token);
@@ -2161,18 +2253,61 @@
         }
     }
 
+    /**
+     * Get or create the user restrictions array for a given client if it doesn't already exist.
+     *
+     * @param token the binder client creating the restriction.
+     * @param userHandle the user handle to create a restriction for.
+     *
+     * @return the array of restriction states for each AppOps code.
+     */
     private boolean[] getOrCreateUserRestrictionsForToken(IBinder token, int userHandle) {
-        SparseArray<boolean[]> perTokenRestrictions = mOpUserRestrictions.get(token);
+        SparseArray<Pair<boolean[], SparseArray<ArraySet<String>>>> perTokenRestrictions =
+                mOpUserRestrictions.get(token);
+
         if (perTokenRestrictions == null) {
-            perTokenRestrictions = new SparseArray<>();
+            perTokenRestrictions =
+                    new SparseArray<Pair<boolean[], SparseArray<ArraySet<String>>>>();
             mOpUserRestrictions.put(token, perTokenRestrictions);
         }
-        boolean[] opRestrictions = perTokenRestrictions.get(userHandle);
-        if (opRestrictions == null) {
-            opRestrictions = new boolean[AppOpsManager._NUM_OP];
-            perTokenRestrictions.put(userHandle, opRestrictions);
+
+        Pair<boolean[], SparseArray<ArraySet<String>>> restrictions =
+                perTokenRestrictions.get(userHandle);
+
+        if (restrictions == null) {
+            restrictions = new Pair<boolean[], SparseArray<ArraySet<String>>>(
+                    new boolean[AppOpsManager._NUM_OP], new SparseArray<ArraySet<String>>());
+            perTokenRestrictions.put(userHandle, restrictions);
         }
-        return opRestrictions;
+
+        return restrictions.first;
+    }
+
+    /**
+     * Get the per-package exemptions for each AppOps code for a given client and userHandle.
+     *
+     * @param token the binder client to get the exemptions for.
+     * @param userHandle the user handle to get the exemptions for.
+     *
+     * @return a mapping from the AppOps code to a set of packages exempt for that code.
+     */
+    private SparseArray<ArraySet<String>> getUserPackageExemptionsForToken(IBinder token,
+            int userHandle) {
+        SparseArray<Pair<boolean[], SparseArray<ArraySet<String>>>> perTokenRestrictions =
+                mOpUserRestrictions.get(token);
+
+        if (perTokenRestrictions == null) {
+            return null; // Don't create user restrictions accidentally
+        }
+
+        Pair<boolean[], SparseArray<ArraySet<String>>> restrictions =
+                perTokenRestrictions.get(userHandle);
+
+        if (restrictions == null) {
+            return null; // Don't create user restrictions accidentally
+        }
+
+        return restrictions.second;
     }
 
     private void checkSystemUid(String function) {
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index e241a4a..799a763 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -761,6 +761,11 @@
         if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
             if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth.");
             sendEnableMsg(mQuietEnableExternal);
+        } else if (!isNameAndAddressSet()) {
+            if (DBG) Slog.d(TAG, "Getting adapter name and address");
+            enable();
+            waitForOnOff(true, false);
+            disable(true);
         }
     }
 
@@ -1001,6 +1006,7 @@
                 }
             }
         }
+
         // mAddress is accessed from outside.
         // It is alright without a lock. Here, bluetooth is off, no other thread is
         // changing mAddress
@@ -1181,6 +1187,15 @@
                             Slog.e(TAG,"Unable to call configHciSnoopLog", e);
                         }
 
+                        if (!isNameAndAddressSet()) {
+                            try {
+                                storeNameAndAddress(mBluetooth.getName(),
+                                                    mBluetooth.getAddress());
+                            } catch (RemoteException re) {
+                                Slog.e(TAG, "Unable to grab names", re);
+                            }
+                        }
+
                         //Register callback object
                         try {
                             mBluetooth.registerCallback(mBluetoothCallback);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 86040c2..b7fca1a 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1784,6 +1784,38 @@
         return false;
     }
 
+    private void dumpNetworkDiagnostics(IndentingPrintWriter pw) {
+        final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>();
+        final long DIAG_TIME_MS = 5000;
+        for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+            // Start gathering diagnostic information.
+            netDiags.add(new NetworkDiagnostics(
+                    nai.network,
+                    new LinkProperties(nai.linkProperties),  // Must be a copy.
+                    DIAG_TIME_MS));
+        }
+
+        for (NetworkDiagnostics netDiag : netDiags) {
+            pw.println();
+            netDiag.waitForMeasurements();
+            netDiag.dump(pw);
+        }
+    }
+
+    private void dumpApf(IndentingPrintWriter pw) {
+        pw.println("APF filters:");
+        pw.increaseIndent();
+        for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+            if (nai.apfFilter != null) {
+                pw.println(nai.name() + ":");
+                pw.increaseIndent();
+                nai.apfFilter.dump(pw);
+                pw.decreaseIndent();
+            }
+        }
+        pw.decreaseIndent();
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
@@ -1796,23 +1828,13 @@
             return;
         }
 
-        final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>();
         if (argsContain(args, "--diag")) {
-            final long DIAG_TIME_MS = 5000;
-            for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
-                // Start gathering diagnostic information.
-                netDiags.add(new NetworkDiagnostics(
-                        nai.network,
-                        new LinkProperties(nai.linkProperties),  // Must be a copy.
-                        DIAG_TIME_MS));
-            }
+            dumpNetworkDiagnostics(pw);
+            return;
+        }
 
-            for (NetworkDiagnostics netDiag : netDiags) {
-                pw.println();
-                netDiag.waitForMeasurements();
-                netDiag.dump(pw);
-            }
-
+        if (argsContain(args, "apf")) {
+            dumpApf(pw);
             return;
         }
 
@@ -1878,6 +1900,9 @@
         pw.println();
         mKeepaliveTracker.dump(pw);
 
+        pw.println();
+        dumpApf(pw);
+
         if (mInetLog != null && mInetLog.size() > 0) {
             pw.println();
             pw.println("Inet condition reports:");
@@ -3253,8 +3278,12 @@
             }
             int user = UserHandle.getUserId(Binder.getCallingUid());
             synchronized(mVpns) {
-                setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, mVpns.get(user),
-                            profile));
+                Vpn vpn = mVpns.get(user);
+                if (vpn == null) {
+                    Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown");
+                    return false;
+                }
+                setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, vpn, profile));
             }
         } else {
             setLockdownTracker(null);
diff --git a/services/core/java/com/android/server/ContextHubSystemService.java b/services/core/java/com/android/server/ContextHubSystemService.java
new file mode 100644
index 0000000..1b85632
--- /dev/null
+++ b/services/core/java/com/android/server/ContextHubSystemService.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.hardware.location.ContextHubService;
+import android.content.Context;
+import android.util.Log;
+
+class ContextHubSystemService extends SystemService {
+    private static final String TAG = "ContextHubSystemService";
+    private final ContextHubService mContextHubService;
+
+    public ContextHubSystemService(Context context) {
+        super(context);
+        mContextHubService = new ContextHubService(context);
+    }
+
+    @Override
+    public void onStart() {
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+            Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY");
+            publishBinderService(ContextHubService.CONTEXTHUB_SERVICE, mContextHubService);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 62fa7d5..7bf4b56 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -120,6 +120,7 @@
     private AlarmManager mAlarmManager;
     private IBatteryStats mBatteryStats;
     private PowerManagerInternal mLocalPowerManager;
+    private AlarmManagerService.LocalService mLocalAlarmManager;
     private INetworkPolicyManager mNetworkPolicyManager;
     private DisplayManager mDisplayManager;
     private SensorManager mSensorManager;
@@ -269,6 +270,17 @@
     private int[] mPowerSaveWhitelistAllAppIdArray = new int[0];
 
     /**
+     * App IDs that have been white-listed by the user to opt out of power save restrictions.
+     */
+    private final SparseBooleanArray mPowerSaveWhitelistUserAppIds = new SparseBooleanArray();
+
+    /**
+     * Current app IDs that are in the user power save white list.  This array can
+     * be shared with others because it will not be modified once set.
+     */
+    private int[] mPowerSaveWhitelistUserAppIdArray = new int[0];
+
+    /**
      * List of end times for UIDs that are temporarily marked as being allowed to access
      * the network and acquire wakelocks. Times are in milliseconds.
      */
@@ -964,6 +976,10 @@
             return getSystemPowerWhitelistInternal();
         }
 
+        @Override public String[] getUserPowerWhitelist() {
+            return getUserPowerWhitelistInternal();
+        }
+
         @Override public String[] getFullPowerWhitelistExceptIdle() {
             return getFullPowerWhitelistExceptIdleInternal();
         }
@@ -980,6 +996,10 @@
             return getAppIdWhitelistInternal();
         }
 
+        @Override public int[] getAppIdUserWhitelist() {
+            return getAppIdUserWhitelistInternal();
+        }
+
         @Override public int[] getAppIdTempWhitelist() {
             return getAppIdTempWhitelistInternal();
         }
@@ -1161,6 +1181,7 @@
                 mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
                 mBatteryStats = BatteryStatsService.getService();
                 mLocalPowerManager = getLocalService(PowerManagerInternal.class);
+                mLocalAlarmManager = getLocalService(AlarmManagerService.LocalService.class);
                 mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
                         ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
                 mDisplayManager = (DisplayManager) getContext().getSystemService(
@@ -1227,6 +1248,7 @@
                 getContext().registerReceiver(mReceiver, filter);
 
                 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
+                mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray);
 
                 mDisplayManager.registerDisplayListener(mDisplayListener, null);
                 updateDisplayLocked();
@@ -1291,6 +1313,17 @@
         }
     }
 
+    public String[] getUserPowerWhitelistInternal() {
+        synchronized (this) {
+            int size = mPowerSaveWhitelistUserApps.size();
+            String[] apps = new String[size];
+            for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
+                apps[i] = mPowerSaveWhitelistUserApps.keyAt(i);
+            }
+            return apps;
+        }
+    }
+
     public String[] getFullPowerWhitelistExceptIdleInternal() {
         synchronized (this) {
             int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size();
@@ -1351,6 +1384,12 @@
         }
     }
 
+    public int[] getAppIdUserWhitelistInternal() {
+        synchronized (this) {
+            return mPowerSaveWhitelistUserAppIdArray;
+        }
+    }
+
     public int[] getAppIdTempWhitelistInternal() {
         synchronized (this) {
             return mTempWhitelistAppIdArray;
@@ -1993,11 +2032,15 @@
     private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
             ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
         outAppIds.clear();
-        for (int i=0; i<systemApps.size(); i++) {
-            outAppIds.put(systemApps.valueAt(i), true);
+        if (systemApps != null) {
+            for (int i = 0; i < systemApps.size(); i++) {
+                outAppIds.put(systemApps.valueAt(i), true);
+            }
         }
-        for (int i=0; i<userApps.size(); i++) {
-            outAppIds.put(userApps.valueAt(i), true);
+        if (userApps != null) {
+            for (int i = 0; i < userApps.size(); i++) {
+                outAppIds.put(userApps.valueAt(i), true);
+            }
         }
         int size = outAppIds.size();
         int[] appids = new int[size];
@@ -2012,6 +2055,8 @@
                 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
         mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
                 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
+        mPowerSaveWhitelistUserAppIdArray = buildAppIdArray(null,
+                mPowerSaveWhitelistUserApps, mPowerSaveWhitelistUserAppIds);
         if (mLocalPowerManager != null) {
             if (DEBUG) {
                 Slog.d(TAG, "Setting wakelock whitelist to "
@@ -2019,6 +2064,13 @@
             }
             mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
         }
+        if (mLocalAlarmManager != null) {
+            if (DEBUG) {
+                Slog.d(TAG, "Setting alarm whitelist to "
+                        + Arrays.toString(mPowerSaveWhitelistUserAppIdArray));
+            }
+            mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray);
+        }
     }
 
     private void updateTempWhitelistAppIdsLocked() {
@@ -2536,6 +2588,15 @@
                     pw.println();
                 }
             }
+            size = mPowerSaveWhitelistUserAppIds.size();
+            if (size > 0) {
+                pw.println("  Whitelist user app ids:");
+                for (int i = 0; i < size; i++) {
+                    pw.print("    ");
+                    pw.print(mPowerSaveWhitelistUserAppIds.keyAt(i));
+                    pw.println();
+                }
+            }
             size = mPowerSaveWhitelistAllAppIds.size();
             if (size > 0) {
                 pw.println("  Whitelist all app ids:");
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index a93b4d8..00a49bd 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -456,6 +456,7 @@
     class SettingsObserver extends ContentObserver {
         int mUserId;
         boolean mRegistered = false;
+        @NonNull
         String mLastEnabled = "";
 
         /**
@@ -3588,6 +3589,7 @@
         private static final String ATTR_IME_SUBTYPE_MODE = "imeSubtypeMode";
         private static final String ATTR_IME_SUBTYPE_EXTRA_VALUE = "imeSubtypeExtraValue";
         private static final String ATTR_IS_AUXILIARY = "isAuxiliary";
+        private static final String ATTR_IS_ASCII_CAPABLE = "isAsciiCapable";
         private final AtomicFile mAdditionalInputMethodSubtypeFile;
         private final HashMap<String, InputMethodInfo> mMethodMap;
         private final HashMap<String, List<InputMethodSubtype>> mAdditionalSubtypesMap =
@@ -3684,6 +3686,8 @@
                         out.attribute(null, ATTR_IME_SUBTYPE_EXTRA_VALUE, subtype.getExtraValue());
                         out.attribute(null, ATTR_IS_AUXILIARY,
                                 String.valueOf(subtype.isAuxiliary() ? 1 : 0));
+                        out.attribute(null, ATTR_IS_ASCII_CAPABLE,
+                                String.valueOf(subtype.isAsciiCapable() ? 1 : 0));
                         out.endTag(null, NODE_SUBTYPE);
                     }
                     out.endTag(null, NODE_IMI);
@@ -3749,6 +3753,8 @@
                                 parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
                         final boolean isAuxiliary = "1".equals(String.valueOf(
                                 parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
+                        final boolean isAsciiCapable = "1".equals(String.valueOf(
+                                parser.getAttributeValue(null, ATTR_IS_ASCII_CAPABLE)));
                         final InputMethodSubtype subtype = new InputMethodSubtypeBuilder()
                                 .setSubtypeNameResId(label)
                                 .setSubtypeIconResId(icon)
@@ -3757,6 +3763,7 @@
                                 .setSubtypeMode(imeSubtypeMode)
                                 .setSubtypeExtraValue(imeSubtypeExtraValue)
                                 .setIsAuxiliary(isAuxiliary)
+                                .setIsAsciiCapable(isAsciiCapable)
                                 .build();
                         tempSubtypesArray.add(subtype);
                     }
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 329f716..07c10b0 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -49,6 +49,7 @@
 import android.app.ActivityManagerNative;
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.net.INetd;
 import android.net.INetworkManagementEventObserver;
 import android.net.InterfaceConfiguration;
 import android.net.IpPrefix;
@@ -122,7 +123,7 @@
     private static final String TAG = "NetworkManagement";
     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
     private static final String NETD_TAG = "NetdConnector";
-    private static final String NETD_SOCKET_NAME = "netd";
+    private static final String NETD_SERVICE_NAME = "netd";
 
     private static final int MAX_UID_RANGES_PER_COMMAND = 10;
 
@@ -188,6 +189,8 @@
     private final Handler mFgHandler;
     private final Handler mDaemonHandler;
 
+    private INetd mNetdService;
+
     private IBatteryStats mBatteryStats;
 
     private final Thread mThread;
@@ -306,7 +309,7 @@
     }
 
     public static NetworkManagementService create(Context context) throws InterruptedException {
-        return create(context, NETD_SOCKET_NAME);
+        return create(context, NETD_SERVICE_NAME);
     }
 
     public void systemReady() {
@@ -515,6 +518,15 @@
      * existing in-memory rules.
      */
     private void prepareNativeDaemon() {
+        boolean nativeServiceAvailable = false;
+        try {
+            mNetdService = INetd.Stub.asInterface(ServiceManager.getService(NETD_SERVICE_NAME));
+            nativeServiceAvailable = mNetdService.isAlive();
+        } catch (RemoteException e) {}
+        if (!nativeServiceAvailable) {
+            Slog.wtf(TAG, "Can't connect to NativeNetdService " + NETD_SERVICE_NAME);
+        }
+
         mBandwidthControlEnabled = false;
 
         // only enable bandwidth control when support exists
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index 306e933..3eb20a0 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -28,6 +28,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
@@ -464,9 +465,10 @@
             return null;
         }
         synchronized (mSpellCheckerMap) {
-            final String subtypeHashCodeStr = mSettings.getSelectedSpellCheckerSubtype();
+            final int subtypeHashCode =
+                    mSettings.getSelectedSpellCheckerSubtype(SpellCheckerSubtype.SUBTYPE_ID_NONE);
             if (DBG) {
-                Slog.w(TAG, "getCurrentSpellCheckerSubtype: " + subtypeHashCodeStr);
+                Slog.w(TAG, "getCurrentSpellCheckerSubtype: " + subtypeHashCode);
             }
             final SpellCheckerInfo sci = getCurrentSpellChecker(null);
             if (sci == null || sci.getSubtypeCount() == 0) {
@@ -475,17 +477,12 @@
                 }
                 return null;
             }
-            final int hashCode;
-            if (!TextUtils.isEmpty(subtypeHashCodeStr)) {
-                hashCode = Integer.valueOf(subtypeHashCodeStr);
-            } else {
-                hashCode = 0;
-            }
-            if (hashCode == 0 && !allowImplicitlySelectedSubtype) {
+            if (subtypeHashCode == SpellCheckerSubtype.SUBTYPE_ID_NONE
+                    && !allowImplicitlySelectedSubtype) {
                 return null;
             }
             String candidateLocale = null;
-            if (hashCode == 0) {
+            if (subtypeHashCode == 0) {
                 // Spell checker language settings == "auto"
                 final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
                 if (imm != null) {
@@ -507,7 +504,7 @@
             SpellCheckerSubtype candidate = null;
             for (int i = 0; i < sci.getSubtypeCount(); ++i) {
                 final SpellCheckerSubtype scs = sci.getSubtypeAt(i);
-                if (hashCode == 0) {
+                if (subtypeHashCode == 0) {
                     final String scsLocale = scs.getLocale();
                     if (candidateLocale.equals(scsLocale)) {
                         return scs;
@@ -518,7 +515,7 @@
                             candidate = scs;
                         }
                     }
-                } else if (scs.hashCode() == hashCode) {
+                } else if (scs.hashCode() == subtypeHashCode) {
                     if (DBG) {
                         Slog.w(TAG, "Return subtype " + scs.hashCode() + ", input= " + locale
                                 + ", " + scs.getLocale());
@@ -1096,12 +1093,15 @@
             }
         }
 
-        private String getString(final String key) {
+        @Nullable
+        private String getString(@NonNull final String key, @Nullable final String defaultValue) {
+            final String result;
             if (mCopyOnWrite && mCopyOnWriteDataStore.containsKey(key)) {
-                final String result = mCopyOnWriteDataStore.get(key);
-                return result != null ? result : "";
+                result = mCopyOnWriteDataStore.get(key);
+            } else {
+                result = Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
             }
-            return Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId);
+            return result != null ? result : defaultValue;
         }
 
         private void putInt(final String key, final int value) {
@@ -1149,24 +1149,31 @@
             return mCurrentUserId;
         }
 
-        public void putSelectedSpellChecker(String sciId) {
-            putString(Settings.Secure.SELECTED_SPELL_CHECKER, sciId);
+        public void putSelectedSpellChecker(@Nullable String sciId) {
+            if (TextUtils.isEmpty(sciId)) {
+                // OK to coalesce to null, since getSelectedSpellChecker() can take care of the
+                // empty data scenario.
+                putString(Settings.Secure.SELECTED_SPELL_CHECKER, null);
+            } else {
+                putString(Settings.Secure.SELECTED_SPELL_CHECKER, sciId);
+            }
         }
 
         public void putSelectedSpellCheckerSubtype(int hashCode) {
-            putString(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(hashCode));
+            putInt(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, hashCode);
         }
 
         public void setSpellCheckerEnabled(boolean enabled) {
             putBoolean(Settings.Secure.SPELL_CHECKER_ENABLED, enabled);
         }
 
+        @NonNull
         public String getSelectedSpellChecker() {
-            return getString(Settings.Secure.SELECTED_SPELL_CHECKER);
+            return getString(Settings.Secure.SELECTED_SPELL_CHECKER, "");
         }
 
-        public String getSelectedSpellCheckerSubtype() {
-            return getString(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE);
+        public int getSelectedSpellCheckerSubtype(final int defaultValue) {
+            return getInt(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, defaultValue);
         }
 
         public boolean isSpellCheckerEnabled() {
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 772a15c..4198af9 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -64,9 +64,11 @@
 
     // Which native processes to dump into dropbox's stack traces
     public static final String[] NATIVE_STACKS_OF_INTEREST = new String[] {
+        "/system/bin/audioserver",
         "/system/bin/mediaserver",
         "/system/bin/sdcard",
-        "/system/bin/surfaceflinger"
+        "/system/bin/surfaceflinger",
+        "media.log"
     };
 
     static Watchdog sWatchdog;
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index a63faf1..d4dd505 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -47,6 +47,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
+import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -2460,31 +2461,12 @@
         public void onResult(Bundle result) {
             mNumResults++;
             Intent intent = null;
-
             if (result != null
                     && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
-                /*
-                 * The Authenticator API allows third party authenticators to
-                 * supply arbitrary intents to other apps that they can run,
-                 * this can be very bad when those apps are in the system like
-                 * the System Settings.
-                 */
-                int authenticatorUid = Binder.getCallingUid();
-                long bid = Binder.clearCallingIdentity();
-                try {
-                    PackageManager pm = mContext.getPackageManager();
-                    ResolveInfo resolveInfo = pm.resolveActivityAsUser(intent, 0, mAccounts.userId);
-                    int targetUid = resolveInfo.activityInfo.applicationInfo.uid;
-                    if (PackageManager.SIGNATURE_MATCH != pm.checkSignatures(authenticatorUid,
-                            targetUid)) {
-                        throw new SecurityException("Activity to be started with KEY_INTENT must "
-                                + "share Authenticator's signatures");
-                    }
-                } finally {
-                    Binder.restoreCallingIdentity(bid);
-                }
+                checkKeyIntent(
+                        Binder.getCallingUid(),
+                        intent);
             }
-
             IAccountManagerResponse response;
             if (mExpectActivityLaunch && result != null
                     && result.containsKey(AccountManager.KEY_INTENT)) {
@@ -3569,6 +3551,36 @@
             return response;
         }
 
+        /**
+         * Checks Intents, supplied via KEY_INTENT, to make sure that they don't violate our
+         * security policy.
+         *
+         * In particular we want to make sure that the Authenticator doesn't try to trick users
+         * into launching aribtrary intents on the device via by tricking to click authenticator
+         * supplied entries in the system Settings app.
+         */
+        protected void checkKeyIntent(
+                int authUid,
+                Intent intent) throws SecurityException {
+            long bid = Binder.clearCallingIdentity();
+            try {
+                PackageManager pm = mContext.getPackageManager();
+                ResolveInfo resolveInfo = pm.resolveActivityAsUser(intent, 0, mAccounts.userId);
+                ActivityInfo targetActivityInfo = resolveInfo.activityInfo;
+                int targetUid = targetActivityInfo.applicationInfo.uid;
+                if (PackageManager.SIGNATURE_MATCH != pm.checkSignatures(authUid, targetUid)) {
+                    String pkgName = targetActivityInfo.packageName;
+                    String activityName = targetActivityInfo.name;
+                    String tmpl = "KEY_INTENT resolved to an Activity (%s) in a package (%s) that "
+                            + "does not share a signature with the supplying authenticator (%s).";
+                    throw new SecurityException(
+                            String.format(tmpl, activityName, pkgName, mAccountType));
+                }
+            } finally {
+                Binder.restoreCallingIdentity(bid);
+            }
+        }
+
         private void close() {
             synchronized (mSessions) {
                 if (mSessions.remove(toString()) == null) {
@@ -3711,27 +3723,9 @@
             }
             if (result != null
                     && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
-                /*
-                 * The Authenticator API allows third party authenticators to
-                 * supply arbitrary intents to other apps that they can run,
-                 * this can be very bad when those apps are in the system like
-                 * the System Settings.
-                 */
-                int authenticatorUid = Binder.getCallingUid();
-                long bid = Binder.clearCallingIdentity();
-                try {
-                    PackageManager pm = mContext.getPackageManager();
-                    ResolveInfo resolveInfo = pm.resolveActivityAsUser(intent, 0, mAccounts.userId);
-                    int targetUid = resolveInfo.activityInfo.applicationInfo.uid;
-                    if (PackageManager.SIGNATURE_MATCH !=
-                            pm.checkSignatures(authenticatorUid, targetUid)) {
-                        throw new SecurityException(
-                                "Activity to be started with KEY_INTENT must " +
-                               "share Authenticator's signatures");
-                    }
-                } finally {
-                    Binder.restoreCallingIdentity(bid);
-                }
+                checkKeyIntent(
+                        Binder.getCallingUid(),
+                        intent);
             }
             if (result != null
                     && !TextUtils.isEmpty(result.getString(AccountManager.KEY_AUTHTOKEN))) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7ff3e66..6361db5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -352,6 +352,11 @@
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
+import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
+import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_RELAUNCH;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_IN_PLACE;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN;
+import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_FRONT;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
@@ -537,9 +542,11 @@
     final ActivityStarter mActivityStarter;
 
     /** Task stack change listeners. */
-    private RemoteCallbackList<ITaskStackListener> mTaskStackListeners =
+    private final RemoteCallbackList<ITaskStackListener> mTaskStackListeners =
             new RemoteCallbackList<ITaskStackListener>();
 
+    final InstrumentationReporter mInstrumentationReporter = new InstrumentationReporter();
+
     public IntentFirewall mIntentFirewall;
 
     // Whether we should show our dialogs (ANR, crash, etc) or just perform their
@@ -3260,9 +3267,9 @@
 
     boolean isNextTransitionForward() {
         int transit = mWindowManager.getPendingAppTransition();
-        return transit == AppTransition.TRANSIT_ACTIVITY_OPEN
-                || transit == AppTransition.TRANSIT_TASK_OPEN
-                || transit == AppTransition.TRANSIT_TASK_TO_FRONT;
+        return transit == TRANSIT_ACTIVITY_OPEN
+                || transit == TRANSIT_TASK_OPEN
+                || transit == TRANSIT_TASK_TO_FRONT;
     }
 
     int startIsolatedProcess(String entryPoint, String[] entryPointArgs,
@@ -5270,6 +5277,10 @@
     public boolean clearApplicationUserData(final String packageName,
             final IPackageDataObserver observer, int userId) {
         enforceNotIsolatedCaller("clearApplicationUserData");
+        int uid = Binder.getCallingUid();
+        int pid = Binder.getCallingPid();
+        userId = mUserController.handleIncomingUser(pid, uid, userId, false,
+                ALLOW_FULL_ONLY, "clearApplicationUserData", null);
 
         final DevicePolicyManagerInternal dpmi = LocalServices
                 .getService(DevicePolicyManagerInternal.class);
@@ -5277,10 +5288,6 @@
             throw new SecurityException("Cannot clear data for a device owner or a profile owner");
         }
 
-        int uid = Binder.getCallingUid();
-        int pid = Binder.getCallingPid();
-        userId = mUserController.handleIncomingUser(pid, uid, userId, false,
-                ALLOW_FULL_ONLY, "clearApplicationUserData", null);
         long callingId = Binder.clearCallingIdentity();
         try {
             IPackageManager pm = AppGlobals.getPackageManager();
@@ -5340,6 +5347,7 @@
                 Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
                         Uri.fromParts("package", packageName, null));
                 intent.putExtra(Intent.EXTRA_UID, pkgUid);
+                intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUid));
                 broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
                         null, null, 0, null, null, null, null, false, false, userId);
             } catch (RemoteException e) {
@@ -6489,15 +6497,13 @@
     }
 
     @Override
-    public void keyguardGoingAway(boolean disableWindowAnimations,
-            boolean keyguardGoingToNotificationShade) {
+    public void keyguardGoingAway(int flags) {
         enforceNotIsolatedCaller("keyguardGoingAway");
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
                 if (DEBUG_LOCKSCREEN) logLockScreen("");
-                mWindowManager.keyguardGoingAway(disableWindowAnimations,
-                        keyguardGoingToNotificationShade);
+                mWindowManager.keyguardGoingAway(flags);
                 if (mLockScreenShown == LOCK_SCREEN_SHOWN) {
                     mLockScreenShown = LOCK_SCREEN_HIDDEN;
                     updateSleepIfNeededLocked();
@@ -6907,6 +6913,14 @@
             }
         }
 
+        // We're going to be splicing together extras before sending, so we're
+        // okay poking into any contained extras.
+        if (intents != null) {
+            for (int i = 0; i < intents.length; i++) {
+                intents[i].setDefusable(true);
+            }
+        }
+
         final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0;
         final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0;
         final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0;
@@ -9100,7 +9114,8 @@
                     preserveWindow = false;
                 }
 
-                mStackSupervisor.resizeTaskLocked(task, bounds, resizeMode, preserveWindow);
+                mStackSupervisor.resizeTaskLocked(task, bounds, resizeMode, preserveWindow,
+                        false /* deferResume */);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -9165,7 +9180,7 @@
             throw new IllegalArgumentException("Expected in-place ActivityOption " +
                     "with valid animation");
         }
-        mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_IN_PLACE, false);
+        mWindowManager.prepareAppTransition(TRANSIT_TASK_IN_PLACE, false);
         mWindowManager.overridePendingAppTransitionInPlace(opts.getPackageName(),
                 opts.getCustomInPlaceResId());
         mWindowManager.executeAppTransition();
@@ -9544,6 +9559,55 @@
         }
     }
 
+    @Override
+    public void swapDockedAndFullscreenStack() throws RemoteException {
+        enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "swapDockedAndFullscreenStack()");
+        synchronized (this) {
+            long ident = Binder.clearCallingIdentity();
+            try {
+                final ActivityStack fullscreenStack = mStackSupervisor.getStack(
+                        FULLSCREEN_WORKSPACE_STACK_ID);
+                final TaskRecord topTask = fullscreenStack != null ? fullscreenStack.topTask()
+                        : null;
+                final ActivityStack dockedStack = mStackSupervisor.getStack(DOCKED_STACK_ID);
+                final ArrayList<TaskRecord> tasks = dockedStack != null ? dockedStack.getAllTasks()
+                        : null;
+                if (topTask == null || tasks == null || tasks.size() == 0) {
+                    Slog.w(TAG,
+                            "Unable to swap tasks, either docked or fullscreen stack is empty.");
+                    return;
+                }
+
+                // TODO: App transition
+                mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_RELAUNCH, false);
+
+                // Defer the resume so resume/pausing while moving stacks is dangerous.
+                mStackSupervisor.moveTaskToStackLocked(topTask.taskId, DOCKED_STACK_ID,
+                        false /* toTop */, !FORCE_FOCUS, "swapDockedAndFullscreenStack",
+                        ANIMATE, true /* deferResume */);
+                final int size = tasks.size();
+                for (int i = 0; i < size; i++) {
+                    final int id = tasks.get(i).taskId;
+                    if (id == topTask.taskId) {
+                        continue;
+                    }
+                    mStackSupervisor.moveTaskToStackLocked(id,
+                            FULLSCREEN_WORKSPACE_STACK_ID, true /* toTop */, !FORCE_FOCUS,
+                            "swapDockedAndFullscreenStack", ANIMATE, true /* deferResume */);
+                }
+
+                // Because we deferred the resume, to avoid conflicts with stack switches while
+                // resuming, we need to do it after all the tasks are moved.
+                mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+                mStackSupervisor.resumeFocusedStackTopActivityLocked();
+
+                mWindowManager.executeAppTransition();
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+
     /**
      * Moves the input task to the docked stack.
      *
@@ -11140,7 +11204,6 @@
     }
 
     void finishRunningVoiceLocked() {
-        Slog.d(TAG, "finishRunningVoiceLocked()  >>>>");
         if (mRunningVoice != null) {
             mRunningVoice = null;
             mVoiceWakeLock.release();
@@ -17796,17 +17859,17 @@
             } catch (RemoteException e) {
             }
             if (ii == null) {
-                reportStartInstrumentationFailure(watcher, className,
+                reportStartInstrumentationFailureLocked(watcher, className,
                         "Unable to find instrumentation info for: " + className);
                 return false;
             }
             if (ai == null) {
-                reportStartInstrumentationFailure(watcher, className,
+                reportStartInstrumentationFailureLocked(watcher, className,
                         "Unable to find instrumentation target package: " + ii.targetPackage);
                 return false;
             }
             if (!ai.hasCode()) {
-                reportStartInstrumentationFailure(watcher, className,
+                reportStartInstrumentationFailureLocked(watcher, className,
                         "Instrumentation target has no code: " + ii.targetPackage);
                 return false;
             }
@@ -17821,7 +17884,7 @@
                         + " not allowed because package " + ii.packageName
                         + " does not have a signature matching the target "
                         + ii.targetPackage;
-                reportStartInstrumentationFailure(watcher, className, msg);
+                reportStartInstrumentationFailureLocked(watcher, className, msg);
                 throw new SecurityException(msg);
             }
 
@@ -17852,31 +17915,21 @@
      * @param cn The component name of the instrumentation.
      * @param report The error report.
      */
-    private void reportStartInstrumentationFailure(IInstrumentationWatcher watcher,
+    private void reportStartInstrumentationFailureLocked(IInstrumentationWatcher watcher,
             ComponentName cn, String report) {
         Slog.w(TAG, report);
-        try {
-            if (watcher != null) {
-                Bundle results = new Bundle();
-                results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
-                results.putString("Error", report);
-                watcher.instrumentationStatus(cn, -1, results);
-            }
-        } catch (RemoteException e) {
-            Slog.w(TAG, e);
+        if (watcher != null) {
+            Bundle results = new Bundle();
+            results.putString(Instrumentation.REPORT_KEY_IDENTIFIER, "ActivityManagerService");
+            results.putString("Error", report);
+            mInstrumentationReporter.reportStatus(watcher, cn, -1, results);
         }
     }
 
     void finishInstrumentationLocked(ProcessRecord app, int resultCode, Bundle results) {
         if (app.instrumentationWatcher != null) {
-            try {
-                // NOTE:  IInstrumentationWatcher *must* be oneway here
-                app.instrumentationWatcher.instrumentationFinished(
-                    app.instrumentationClass,
-                    resultCode,
-                    results);
-            } catch (RemoteException e) {
-            }
+            mInstrumentationReporter.reportFinished(app.instrumentationWatcher,
+                    app.instrumentationClass, resultCode, results);
         }
 
         // Can't call out of the system process with a lock held, so post a message.
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index d11b436..26eaa8a 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -20,6 +20,7 @@
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
@@ -1404,22 +1405,37 @@
      * needed. A stack is considered translucent if it don't contain a visible or
      * starting (about to be visible) activity that is fullscreen (opaque).
      * @param starting The currently starting activity or null if there is none.
+     * @param stackBehindId The id of the stack directly behind this one.
      */
-    private boolean isStackTranslucent(ActivityRecord starting) {
+    private boolean isStackTranslucent(ActivityRecord starting, int stackBehindId) {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
             final ArrayList<ActivityRecord> activities = task.mActivities;
             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
-                // examining:
-                // 1. Not Finishing AND (Visible or the Starting activity) AND:
-                // 2. Either:
-                // - Full Screen Activity OR
-                // - On top of Home and our stack is NOT home
-                if (!r.finishing && (r.visible || r == starting) && (r.fullscreen ||
-                        (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()))) {
+                if (r.finishing) {
+                    // We don't factor in finishing activities when determining translucency since
+                    // they will be gone soon.
+                    continue;
+                }
+
+                if (!r.visible && r != starting) {
+                    // Also ignore invisible activities that are not the currently starting
+                    // activity (about to be visible).
+                    continue;
+                }
+
+                if (r.fullscreen) {
+                    // Stack isn't translucent if it has at least one fullscreen activity
+                    // that is visible.
+                    return false;
+                }
+
+                if (!isHomeStack() && r.frontOfTask
+                        && task.isOverHomeStack() && stackBehindId != HOME_STACK_ID) {
+                    // Stack isn't translucent if it's top activity should have the home stack
+                    // behind it and the stack currently behind it isn't the home stack.
                     return false;
                 }
             }
@@ -1475,30 +1491,33 @@
                     : STACK_INVISIBLE;
         }
 
-        // Find the first stack below focused stack that actually got something visible.
-        int belowFocusedIndex = mStacks.indexOf(focusedStack) - 1;
-        while (belowFocusedIndex >= 0 &&
-                mStacks.get(belowFocusedIndex).topRunningActivityLocked() == null) {
-            belowFocusedIndex--;
+        // Find the first stack behind focused stack that actually got something visible.
+        int stackBehindFocusedIndex = mStacks.indexOf(focusedStack) - 1;
+        while (stackBehindFocusedIndex >= 0 &&
+                mStacks.get(stackBehindFocusedIndex).topRunningActivityLocked() == null) {
+            stackBehindFocusedIndex--;
         }
         if ((focusedStackId == DOCKED_STACK_ID || focusedStackId == PINNED_STACK_ID)
-                && stackIndex == belowFocusedIndex) {
+                && stackIndex == stackBehindFocusedIndex) {
             // Stacks directly behind the docked or pinned stack are always visible.
             return STACK_VISIBLE;
         }
 
+        final int stackBehindFocusedId = (stackBehindFocusedIndex >= 0)
+                ? mStacks.get(stackBehindFocusedIndex).mStackId : INVALID_STACK_ID;
+
         if (focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
-                && focusedStack.isStackTranslucent(starting)) {
+                && focusedStack.isStackTranslucent(starting, stackBehindFocusedId)) {
             // Stacks behind the fullscreen stack with a translucent activity are always
             // visible so they can act as a backdrop to the translucent activity.
             // For example, dialog activities
-            if (stackIndex == belowFocusedIndex) {
+            if (stackIndex == stackBehindFocusedIndex) {
                 return STACK_VISIBLE;
             }
-            if (belowFocusedIndex >= 0) {
-                final ActivityStack stack = mStacks.get(belowFocusedIndex);
-                if ((stack.mStackId == DOCKED_STACK_ID || stack.mStackId == PINNED_STACK_ID)
-                        && stackIndex == (belowFocusedIndex - 1)) {
+            if (stackBehindFocusedIndex >= 0) {
+                if ((stackBehindFocusedId == DOCKED_STACK_ID
+                        || stackBehindFocusedId == PINNED_STACK_ID)
+                        && stackIndex == (stackBehindFocusedIndex - 1)) {
                     // The stack behind the docked or pinned stack is also visible so we can have a
                     // complete backdrop to the translucent activity when the docked stack is up.
                     return STACK_VISIBLE;
@@ -1523,7 +1542,7 @@
                 return STACK_INVISIBLE;
             }
 
-            if (!stack.isStackTranslucent(starting)) {
+            if (!stack.isStackTranslucent(starting, INVALID_STACK_ID)) {
                 return STACK_INVISIBLE;
             }
         }
@@ -1790,6 +1809,12 @@
             r.app.pendingUiClean = true;
             r.app.thread.scheduleWindowVisibility(r.appToken, true);
             r.stopFreezingScreenLocked(false);
+
+            // The activity may be waiting for stop, but that is no longer
+            // appropriate for it.
+            mStackSupervisor.mStoppingActivities.remove(r);
+            mStackSupervisor.mGoingToSleepActivities.remove(r);
+            mStackSupervisor.mWaitingVisibleActivities.remove(r);
         } catch (Exception e) {
             // Just skip on any failure; we'll make it
             // visible when it next restarts.
@@ -2188,10 +2213,11 @@
 
         ActivityStack lastStack = mStackSupervisor.getLastStack();
         if (next.app != null && next.app.thread != null) {
-            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next);
+            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
+                    + " stopped=" + next.stopped + " visible=" + next.visible);
 
             // This activity is now becoming visible.
-            if (!next.visible) {
+            if (!next.visible || next.stopped) {
                 mWindowManager.setAppVisibility(next.appToken, true);
             }
 
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 48f31f9..d364d85 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2062,7 +2062,8 @@
         }
     }
 
-    boolean resizeTaskLocked(TaskRecord task, Rect bounds, int resizeMode, boolean preserveWindow) {
+    boolean resizeTaskLocked(TaskRecord task, Rect bounds, int resizeMode, boolean preserveWindow,
+            boolean deferResume) {
         if (!task.isResizeable()) {
             Slog.w(TAG, "resizeTask: task " + task + " not resizeable.");
             return true;
@@ -2105,10 +2106,14 @@
             if (r != null) {
                 final ActivityStack stack = task.stack;
                 kept = stack.ensureActivityConfigurationLocked(r, 0, preserveWindow);
-                // All other activities must be made visible with their correct configuration.
-                ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS);
-                if (!kept) {
-                    resumeFocusedStackTopActivityLocked();
+
+                if (!deferResume) {
+
+                    // All other activities must be made visible with their correct configuration.
+                    ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS);
+                    if (!kept) {
+                        resumeFocusedStackTopActivityLocked();
+                    }
                 }
             }
         }
@@ -2247,6 +2252,12 @@
 
     boolean moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
             String reason, boolean animate) {
+        return moveTaskToStackLocked(taskId, stackId, toTop, forceFocus, reason, animate,
+                false /* deferResume */);
+    }
+
+    boolean moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
+            String reason, boolean animate, boolean deferResume) {
         final TaskRecord task = anyTaskForIdLocked(taskId);
         if (task == null) {
             Slog.w(TAG, "moveTaskToStack: no task for id=" + taskId);
@@ -2297,16 +2308,19 @@
 
             // Make sure the task has the appropriate bounds/size for the stack it is in.
             if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
-                kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow);
+                kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM,
+                        !mightReplaceWindow, deferResume);
             } else if (stackId == FREEFORM_WORKSPACE_STACK_ID) {
                 Rect bounds = task.getLaunchBounds();
                 if (bounds == null) {
                     stack.layoutTaskInStack(task, null);
                     bounds = task.mBounds;
                 }
-                kept = resizeTaskLocked(task, bounds, RESIZE_MODE_FORCED, !mightReplaceWindow);
+                kept = resizeTaskLocked(task, bounds, RESIZE_MODE_FORCED, !mightReplaceWindow,
+                        deferResume);
             } else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) {
-                kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow);
+                kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM,
+                        !mightReplaceWindow, deferResume);
             }
         } finally {
             mWindowManager.continueSurfaceLayout();
@@ -2319,10 +2333,13 @@
             mWindowManager.scheduleClearReplacingWindowIfNeeded(topActivity.appToken, !kept);
         }
 
-        // The task might have already been running and its visibility needs to be synchronized with
-        // the visibility of the stack / windows.
-        ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
-        resumeFocusedStackTopActivityLocked();
+        if (!deferResume) {
+
+            // The task might have already been running and its visibility needs to be synchronized with
+            // the visibility of the stack / windows.
+            ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
+            resumeFocusedStackTopActivityLocked();
+        }
 
         showNonResizeableDockToastIfNeeded(task, preferredLaunchStackId, stackId);
 
@@ -2372,6 +2389,11 @@
             if (task.mActivities.size() == 1) {
                 // There is only one activity in the task. So, we can just move the task over to
                 // the stack without re-parenting the activity in a different task.
+                if (task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE) {
+                    // Move the home stack forward if the task we just moved to the pinned stack
+                    // was launched from home so home should be visible behind it.
+                    moveHomeStackToFront(reason);
+                }
                 moveTaskToStackLocked(
                         task.taskId, PINNED_STACK_ID, ON_TOP, FORCE_FOCUS, reason, !ANIMATE);
             } else {
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index e4b4c2d..13d90e3 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -29,6 +29,7 @@
 import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
 
 import android.app.KeyguardManager;
+import android.app.admin.DevicePolicyManagerInternal;
 import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -40,6 +41,7 @@
 import android.os.UserManager;
 
 import com.android.internal.app.UnlaunchableAppActivity;
+import com.android.server.LocalServices;
 
 /**
  * A class that contains activity intercepting logic for {@link ActivityStarter#startActivityLocked}
@@ -133,8 +135,10 @@
                 (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) == 0) {
             return false;
         }
-        mIntent = UnlaunchableAppActivity.createPackageSuspendedDialogIntent(mAInfo.packageName,
-                mUserId);
+        DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService(
+                DevicePolicyManagerInternal.class);
+        mIntent = devicePolicyManager.createPackageSuspendedDialogIntent(
+                mAInfo.packageName, mUserId);
         mCallingPid = mRealCallingPid;
         mCallingUid = mRealCallingUid;
         mResolvedType = null;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 83ad2a7..fa62c98 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1327,19 +1327,31 @@
                     intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
                 }
                 mMovedHome = true;
-                final ActivityStack launchStack =
-                        getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
-                                mOptions, true);
-                if (launchStack == null || launchStack == mTargetStack) {
-                    // We only want to move to the front, if we aren't going to launch on a
-                    // different stack. If we launch on a different stack, we will put the
-                    // task on top there.
-                    mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
-                            mOptions, mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
-                    mMovedToFront = true;
+
+                // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
+                // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
+                // So no point resuming any of the activities here, it just wastes one extra
+                // resuming, plus enter AND exit transitions.
+                // Here we only want to bring the target stack forward. Transition will be applied
+                // to the new activity that's started after the old ones are gone.
+                final boolean willClearTask =
+                        (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
+                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
+                if (!willClearTask) {
+                    final ActivityStack launchStack = getLaunchStack(
+                            mStartActivity, mLaunchFlags, mStartActivity.task, mOptions, true);
+                    if (launchStack == null || launchStack == mTargetStack) {
+                        // We only want to move to the front, if we aren't going to launch on a
+                        // different stack. If we launch on a different stack, we will put the
+                        // task on top there.
+                        mTargetStack.moveTaskToFrontLocked(
+                                intentActivity.task, mNoAnimation, mOptions,
+                                mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
+                        mMovedToFront = true;
+                    }
+                    mOptions = null;
                 }
                 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
-                mOptions = null;
             }
         }
         if (!mMovedToFront && mDoResume) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 28882de..71a1f97 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -32,6 +32,7 @@
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelFormatException;
+import android.os.PowerManager;
 import android.os.PowerManagerInternal;
 import android.os.Process;
 import android.os.RemoteException;
@@ -39,6 +40,9 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.os.health.HealthStatsParceler;
+import android.os.health.HealthStatsWriter;
+import android.os.health.UidHealthStats;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.ModemActivityInfo;
 import android.telephony.SignalStrength;
@@ -65,7 +69,9 @@
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CodingErrorAction;
 import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 
 /**
  * All information we are collecting about things that can happen that impact
@@ -1419,4 +1425,88 @@
             }
         }
     }
+
+    /**
+     * Gets a snapshot of the system health for a particular uid.
+     */
+    @Override
+    public HealthStatsParceler takeUidSnapshot(int requestUid) {
+        if (requestUid != Binder.getCallingUid()) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.BATTERY_STATS, null);
+        }
+        long ident = Binder.clearCallingIdentity();
+        try {
+            updateExternalStats("get-health-stats-for-uid",
+                    BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
+            synchronized (mStats) {
+                return getHealthStatsForUidLocked(requestUid);
+            }
+        } catch (Exception ex) {
+            Slog.d(TAG, "Crashed while writing for takeUidSnapshot(" + requestUid + ")", ex);
+            throw ex;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    /**
+     * Gets a snapshot of the system health for a number of uids.
+     */
+    @Override
+    public HealthStatsParceler[] takeUidSnapshots(int[] requestUids) {
+        if (!onlyCaller(requestUids)) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.BATTERY_STATS, null);
+        }
+        long ident = Binder.clearCallingIdentity();
+        int i=-1;
+        try {
+            updateExternalStats("get-health-stats-for-uids",
+                    BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
+            synchronized (mStats) {
+                final int N = requestUids.length;
+                final HealthStatsParceler[] results = new HealthStatsParceler[N];
+                for (i=0; i<N; i++) {
+                    results[i] = getHealthStatsForUidLocked(requestUids[i]);
+                }
+                return results;
+            }
+        } catch (Exception ex) {
+            Slog.d(TAG, "Crashed while writing for takeUidSnapshots("
+                    + Arrays.toString(requestUids) + ") i=" + i, ex);
+            throw ex;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    /**
+     * Returns whether the Binder.getCallingUid is the only thing in requestUids.
+     */
+    private static boolean onlyCaller(int[] requestUids) {
+        final int caller = Binder.getCallingUid();
+        final int N = requestUids.length;
+        for (int i=0; i<N; i++) {
+            if (requestUids[i] != caller) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Gets a HealthStatsParceler for the given uid. You should probably call
+     * updateExternalStats first.
+     */
+    HealthStatsParceler getHealthStatsForUidLocked(int requestUid) {
+        final HealthStatsBatteryStatsWriter writer = new HealthStatsBatteryStatsWriter();
+        final HealthStatsWriter uidWriter = new HealthStatsWriter(UidHealthStats.CONSTANTS);
+        final BatteryStats.Uid uid = mStats.getUidStats().get(requestUid);
+        if (uid != null) {
+            writer.writeUid(uidWriter, mStats, uid);
+        }
+        return new HealthStatsParceler(uidWriter);
+    }
+
 }
diff --git a/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
new file mode 100644
index 0000000..39c6ce6
--- /dev/null
+++ b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
@@ -0,0 +1,473 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.os.BatteryStats;
+import static android.os.BatteryStats.STATS_SINCE_UNPLUGGED;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.os.health.HealthKeys;
+import android.os.health.HealthStatsParceler;
+import android.os.health.HealthStatsWriter;
+import android.os.health.PackageHealthStats;
+import android.os.health.ProcessHealthStats;
+import android.os.health.PidHealthStats;
+import android.os.health.ServiceHealthStats;
+import android.os.health.TimerStat;
+import android.os.health.UidHealthStats;
+import android.util.SparseArray;
+
+import java.util.Map;
+
+public class HealthStatsBatteryStatsWriter {
+
+    private final long mNowRealtime;
+    private final long mNowUptime;
+
+    public HealthStatsBatteryStatsWriter() {
+        mNowRealtime = SystemClock.elapsedRealtime();
+        mNowUptime = SystemClock.uptimeMillis();
+    }
+
+    /**
+     * Writes the contents of a BatteryStats.Uid into a HealthStatsWriter.
+     */
+    public void writeUid(HealthStatsWriter uidWriter, BatteryStats bs, BatteryStats.Uid uid) {
+        int N;
+        BatteryStats.Timer timer;
+        SparseArray<? extends BatteryStats.Uid.Sensor> sensors;
+        SparseArray<? extends BatteryStats.Uid.Pid> pids;
+        BatteryStats.ControllerActivityCounter controller;
+        long sum;
+
+        //
+        // It's a little odd for these first four to be here but it's not the end of the
+        // world. It would be easy enough to duplicate them somewhere else if this API
+        // grows.
+        //
+
+        // MEASUREMENT_REALTIME_BATTERY_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_REALTIME_BATTERY_MS,
+                bs.computeBatteryRealtime(mNowRealtime*1000, STATS_SINCE_UNPLUGGED)/1000);
+
+        // MEASUREMENT_UPTIME_BATTERY_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_UPTIME_BATTERY_MS,
+                bs.computeBatteryUptime(mNowUptime*1000, STATS_SINCE_UNPLUGGED)/1000);
+
+        // MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_REALTIME_SCREEN_OFF_BATTERY_MS,
+                bs.computeBatteryScreenOffRealtime(mNowRealtime*1000, STATS_SINCE_UNPLUGGED)/1000);
+
+        // MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_UPTIME_SCREEN_OFF_BATTERY_MS,
+                bs.computeBatteryScreenOffUptime(mNowUptime*1000, STATS_SINCE_UNPLUGGED)/1000);
+
+        //
+        // Now on to the real per-uid stats...
+        //
+
+        for (final Map.Entry<String,? extends BatteryStats.Uid.Wakelock> entry:
+                uid.getWakelockStats().entrySet()) {
+            final String key = entry.getKey();
+            final BatteryStats.Uid.Wakelock wakelock = entry.getValue();
+
+            // TIMERS_WAKELOCKS_FULL
+            timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_FULL);
+            addTimers(uidWriter, UidHealthStats.TIMERS_WAKELOCKS_FULL, key, timer);
+
+            // TIMERS_WAKELOCKS_PARTIAL
+            timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
+            addTimers(uidWriter, UidHealthStats.TIMERS_WAKELOCKS_PARTIAL, key, timer);
+            
+            // TIMERS_WAKELOCKS_WINDOW
+            timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_WINDOW);
+            addTimers(uidWriter, UidHealthStats.TIMERS_WAKELOCKS_WINDOW, key, timer);
+            
+            // TIMERS_WAKELOCKS_DRAW
+            timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_DRAW);
+            addTimers(uidWriter, UidHealthStats.TIMERS_WAKELOCKS_DRAW, key, timer);
+        }
+        
+        // TIMERS_SYNCS
+        for (final Map.Entry<String,? extends BatteryStats.Timer> entry:
+                uid.getSyncStats().entrySet()) {
+            addTimers(uidWriter, UidHealthStats.TIMERS_SYNCS, entry.getKey(), entry.getValue());
+        }
+
+        // TIMERS_JOBS
+        for (final Map.Entry<String,? extends BatteryStats.Timer> entry:
+                uid.getJobStats().entrySet()) {
+            addTimers(uidWriter, UidHealthStats.TIMERS_JOBS, entry.getKey(), entry.getValue());
+        }
+
+        // TIMERS_SENSORS
+        sensors = uid.getSensorStats();
+        N = sensors.size();
+        for (int i=0; i<N; i++) {
+            int sensorId = sensors.keyAt(i);
+            // Battery Stats stores the GPS sensors with a bogus key in this API. Pull it out
+            // as a separate metric here so as to not expose that in the API.
+            if (sensorId == BatteryStats.Uid.Sensor.GPS) {
+                addTimer(uidWriter, UidHealthStats.TIMER_GPS_SENSOR, sensors.valueAt(i).getSensorTime());
+            } else {
+                addTimers(uidWriter, UidHealthStats.TIMERS_SENSORS, Integer.toString(sensorId),
+                        sensors.valueAt(i).getSensorTime());
+            }
+        }
+
+        // STATS_PIDS
+        pids = uid.getPidStats();
+        N = sensors.size();
+        for (int i=0; i<N; i++) {
+            final HealthStatsWriter writer = new HealthStatsWriter(PidHealthStats.CONSTANTS);
+            writePid(writer, pids.valueAt(i));
+            uidWriter.addStats(UidHealthStats.STATS_PIDS, Integer.toString(pids.keyAt(i)), writer);
+        }
+
+        // STATS_PROCESSES
+        for (final Map.Entry<String,? extends BatteryStats.Uid.Proc> entry:
+                uid.getProcessStats().entrySet()) {
+            final HealthStatsWriter writer = new HealthStatsWriter(ProcessHealthStats.CONSTANTS);
+            writeProc(writer, entry.getValue());
+            uidWriter.addStats(UidHealthStats.STATS_PROCESSES, entry.getKey(), writer);
+        }
+
+        // STATS_PACKAGES
+        for (final Map.Entry<String,? extends BatteryStats.Uid.Pkg> entry:
+                uid.getPackageStats().entrySet()) {
+            final HealthStatsWriter writer = new HealthStatsWriter(PackageHealthStats.CONSTANTS);
+            writePkg(writer, entry.getValue());
+            uidWriter.addStats(UidHealthStats.STATS_PACKAGES, entry.getKey(), writer);
+        }
+
+        controller = uid.getWifiControllerActivity();
+        if (controller != null) {
+            // MEASUREMENT_WIFI_IDLE_MS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_IDLE_MS,
+                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+            // MEASUREMENT_WIFI_RX_MS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_MS,
+                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+            // MEASUREMENT_WIFI_TX_MS
+            sum = 0;
+            for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) {
+                sum += counter.getCountLocked(STATS_SINCE_UNPLUGGED);
+            }
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_MS, sum);
+            // MEASUREMENT_WIFI_POWER_MAMS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_POWER_MAMS,
+                    controller.getPowerCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+        }
+
+        controller = uid.getBluetoothControllerActivity();
+        if (controller != null) {
+            // MEASUREMENT_BLUETOOTH_IDLE_MS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_IDLE_MS,
+                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+            // MEASUREMENT_BLUETOOTH_RX_MS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_MS,
+                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+            // MEASUREMENT_BLUETOOTH_TX_MS
+            sum = 0;
+            for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) {
+                sum += counter.getCountLocked(STATS_SINCE_UNPLUGGED);
+            }
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_MS, sum);
+            // MEASUREMENT_BLUETOOTH_POWER_MAMS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_POWER_MAMS,
+                    controller.getPowerCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+        }
+
+        controller = uid.getModemControllerActivity();
+        if (controller != null) {
+            // MEASUREMENT_MOBILE_IDLE_MS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_IDLE_MS,
+                    controller.getIdleTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+            // MEASUREMENT_MOBILE_RX_MS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_MS,
+                    controller.getRxTimeCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+            // MEASUREMENT_MOBILE_TX_MS
+            sum = 0;
+            for (final BatteryStats.LongCounter counter: controller.getTxTimeCounters()) {
+                sum += counter.getCountLocked(STATS_SINCE_UNPLUGGED);
+            }
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_MS, sum);
+            // MEASUREMENT_MOBILE_POWER_MAMS
+            uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_POWER_MAMS,
+                    controller.getPowerCounter().getCountLocked(STATS_SINCE_UNPLUGGED));
+        }
+
+        // MEASUREMENT_WIFI_RUNNING_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RUNNING_MS,
+                uid.getWifiRunningTime(mNowRealtime, STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_WIFI_FULL_LOCK_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_FULL_LOCK_MS,
+                uid.getFullWifiLockTime(mNowRealtime, STATS_SINCE_UNPLUGGED));
+
+        // TIMER_WIFI_SCAN
+        uidWriter.addTimer(UidHealthStats.TIMER_WIFI_SCAN,
+                uid.getWifiScanCount(STATS_SINCE_UNPLUGGED),
+                uid.getWifiScanTime(mNowRealtime, STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_WIFI_MULTICAST_MS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_MULTICAST_MS,
+                uid.getWifiMulticastTime(mNowRealtime, STATS_SINCE_UNPLUGGED));
+
+        // TIMER_AUDIO
+        addTimer(uidWriter, UidHealthStats.TIMER_AUDIO, uid.getAudioTurnedOnTimer());
+
+        // TIMER_VIDEO
+        addTimer(uidWriter, UidHealthStats.TIMER_VIDEO, uid.getVideoTurnedOnTimer());
+
+        // TIMER_FLASHLIGHT
+        addTimer(uidWriter, UidHealthStats.TIMER_FLASHLIGHT, uid.getFlashlightTurnedOnTimer());
+
+        // TIMER_CAMERA
+        addTimer(uidWriter, UidHealthStats.TIMER_CAMERA, uid.getCameraTurnedOnTimer());
+
+        // TIMER_FOREGROUND_ACTIVITY
+        addTimer(uidWriter, UidHealthStats.TIMER_FOREGROUND_ACTIVITY, uid.getForegroundActivityTimer());
+
+        // TIMER_BLUETOOTH_SCAN
+        addTimer(uidWriter, UidHealthStats.TIMER_BLUETOOTH_SCAN, uid.getBluetoothScanTimer());
+
+        // TIMER_PROCESS_STATE_TOP_MS
+        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_TOP_MS,
+                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_TOP));
+
+        // TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS
+        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_FOREGROUND_SERVICE_MS,
+                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE));
+
+        // TIMER_PROCESS_STATE_TOP_SLEEPING_MS
+        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_TOP_SLEEPING_MS,
+                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING));
+
+        // TIMER_PROCESS_STATE_FOREGROUND_MS
+        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_FOREGROUND_MS,
+                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_FOREGROUND));
+
+        // TIMER_PROCESS_STATE_BACKGROUND_MS
+        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_BACKGROUND_MS,
+                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_BACKGROUND));
+
+        // TIMER_PROCESS_STATE_CACHED_MS
+        addTimer(uidWriter, UidHealthStats.TIMER_PROCESS_STATE_CACHED_MS,
+                uid.getProcessStateTimer(BatteryStats.Uid.PROCESS_STATE_CACHED));
+
+        // TIMER_VIBRATOR
+        addTimer(uidWriter, UidHealthStats.TIMER_VIBRATOR, uid.getVibratorOnTimer());
+
+        // MEASUREMENT_OTHER_USER_ACTIVITY_COUNT
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_OTHER_USER_ACTIVITY_COUNT,
+                uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_OTHER,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT,
+                uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_BUTTON,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_TOUCH_USER_ACTIVITY_COUNT,
+                uid.getUserActivityCount(PowerManager.USER_ACTIVITY_EVENT_TOUCH,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_MOBILE_RX_BYTES
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_BYTES,
+                uid.getNetworkActivityBytes(BatteryStats.NETWORK_MOBILE_RX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_MOBILE_TX_BYTES
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_BYTES,
+                uid.getNetworkActivityBytes(BatteryStats.NETWORK_MOBILE_TX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_WIFI_RX_BYTES
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_BYTES,
+                uid.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_RX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_WIFI_TX_BYTES
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_BYTES,
+                uid.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_TX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_BLUETOOTH_RX_BYTES
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_BYTES,
+                uid.getNetworkActivityBytes(BatteryStats.NETWORK_BT_RX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_BLUETOOTH_TX_BYTES
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_BYTES,
+                uid.getNetworkActivityBytes(BatteryStats.NETWORK_BT_TX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_MOBILE_RX_PACKETS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_RX_PACKETS,
+                uid.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_RX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_MOBILE_TX_PACKETS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_MOBILE_TX_PACKETS,
+                uid.getNetworkActivityPackets(BatteryStats.NETWORK_MOBILE_TX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_WIFI_RX_PACKETS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_RX_PACKETS,
+                uid.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_RX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_WIFI_TX_PACKETS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_WIFI_TX_PACKETS,
+                uid.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_TX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_BLUETOOTH_RX_PACKETS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_RX_PACKETS,
+                uid.getNetworkActivityPackets(BatteryStats.NETWORK_BT_RX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_BLUETOOTH_TX_PACKETS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_BLUETOOTH_TX_PACKETS,
+                uid.getNetworkActivityPackets(BatteryStats.NETWORK_BT_TX_DATA,
+                    STATS_SINCE_UNPLUGGED));
+
+        // TIMER_MOBILE_RADIO_ACTIVE
+        uidWriter.addTimer(UidHealthStats.TIMER_MOBILE_RADIO_ACTIVE,
+                uid.getMobileRadioActiveCount(STATS_SINCE_UNPLUGGED),
+                uid.getMobileRadioActiveTime(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_USER_CPU_TIME_US
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_USER_CPU_TIME_US,
+                uid.getUserCpuTimeUs(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_SYSTEM_CPU_TIME_US
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_SYSTEM_CPU_TIME_US,
+                uid.getSystemCpuTimeUs(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_CPU_POWER_MAUS
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_CPU_POWER_MAUS,
+                uid.getCpuPowerMaUs(STATS_SINCE_UNPLUGGED));
+    }
+
+    /**
+     * Writes the contents of a BatteryStats.Uid.Pid into a HealthStatsWriter.
+     */
+    public void writePid(HealthStatsWriter pidWriter, BatteryStats.Uid.Pid pid) {
+        if (pid == null) {
+            return;
+        }
+
+        // MEASUREMENT_WAKE_NESTING_COUNT
+        pidWriter.addMeasurement(PidHealthStats.MEASUREMENT_WAKE_NESTING_COUNT, pid.mWakeNesting);
+
+        // MEASUREMENT_WAKE_SUM_MS
+        pidWriter.addMeasurement(PidHealthStats.MEASUREMENT_WAKE_SUM_MS, pid.mWakeSumMs);
+
+        // MEASUREMENT_WAKE_START_MS
+        pidWriter.addMeasurement(PidHealthStats.MEASUREMENT_WAKE_SUM_MS, pid.mWakeStartMs);
+    }
+
+    /**
+     * Writes the contents of a BatteryStats.Uid.Proc into a HealthStatsWriter.
+     */
+    public void writeProc(HealthStatsWriter procWriter, BatteryStats.Uid.Proc proc) {
+        // MEASUREMENT_USER_TIME_MS
+        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_USER_TIME_MS,
+                proc.getUserTime(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_SYSTEM_TIME_MS
+        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_SYSTEM_TIME_MS,
+                proc.getSystemTime(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_STARTS_COUNT
+        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_STARTS_COUNT,
+                proc.getStarts(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_CRASHES_COUNT
+        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_CRASHES_COUNT,
+                proc.getNumCrashes(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_ANR_COUNT
+        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_ANR_COUNT,
+                proc.getNumAnrs(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_FOREGROUND_MS
+        procWriter.addMeasurement(ProcessHealthStats.MEASUREMENT_FOREGROUND_MS,
+                proc.getForegroundTime(STATS_SINCE_UNPLUGGED));
+    }
+
+    /**
+     * Writes the contents of a BatteryStats.Uid.Pkg into a HealthStatsWriter.
+     */
+    public void writePkg(HealthStatsWriter pkgWriter, BatteryStats.Uid.Pkg pkg) {
+        // STATS_SERVICES
+        for (final Map.Entry<String,? extends BatteryStats.Uid.Pkg.Serv> entry:
+                pkg.getServiceStats().entrySet()) {
+            final HealthStatsWriter writer = new HealthStatsWriter(ServiceHealthStats.CONSTANTS);
+            writeServ(writer, entry.getValue());
+            pkgWriter.addStats(PackageHealthStats.STATS_SERVICES, entry.getKey(), writer);
+        }
+
+        // MEASUREMENTS_WAKEUP_ALARMS_COUNT
+        for (final Map.Entry<String,? extends BatteryStats.Counter> entry:
+                pkg.getWakeupAlarmStats().entrySet()) {
+            final BatteryStats.Counter counter = entry.getValue();
+            if (counter != null) {
+                pkgWriter.addMeasurements(PackageHealthStats.MEASUREMENTS_WAKEUP_ALARMS_COUNT,
+                        entry.getKey(), counter.getCountLocked(STATS_SINCE_UNPLUGGED));
+            }
+        }
+    }
+
+    /**
+     * Writes the contents of a BatteryStats.Uid.Pkg.Serv into a HealthStatsWriter.
+     */
+    public void writeServ(HealthStatsWriter servWriter, BatteryStats.Uid.Pkg.Serv serv) {
+        // MEASUREMENT_START_SERVICE_COUNT
+        servWriter.addMeasurement(ServiceHealthStats.MEASUREMENT_START_SERVICE_COUNT,
+                serv.getStarts(STATS_SINCE_UNPLUGGED));
+
+        // MEASUREMENT_LAUNCH_COUNT
+        servWriter.addMeasurement(ServiceHealthStats.MEASUREMENT_LAUNCH_COUNT,
+                serv.getLaunches(STATS_SINCE_UNPLUGGED));
+    }
+
+    /**
+     * Adds a BatteryStats.Timer into a HealthStatsWriter. Safe to pass a null timer.
+     */
+    private void addTimer(HealthStatsWriter writer, int key, BatteryStats.Timer timer) {
+        if (timer != null) {
+            writer.addTimer(key, timer.getCountLocked(STATS_SINCE_UNPLUGGED),
+                    timer.getTotalTimeLocked(mNowRealtime, STATS_SINCE_UNPLUGGED));
+        }
+    }
+
+    /**
+     * Adds a named BatteryStats.Timer into a HealthStatsWriter. Safe to pass a null timer.
+     */
+    private void addTimers(HealthStatsWriter writer, int key, String name,
+            BatteryStats.Timer timer) {
+        if (timer != null) {
+            writer.addTimers(key, name, new TimerStat(timer.getCountLocked(STATS_SINCE_UNPLUGGED),
+                    timer.getTotalTimeLocked(mNowRealtime, STATS_SINCE_UNPLUGGED)));
+        }
+    }
+}
+
diff --git a/services/core/java/com/android/server/am/InstrumentationReporter.java b/services/core/java/com/android/server/am/InstrumentationReporter.java
new file mode 100644
index 0000000..fdbb73e
--- /dev/null
+++ b/services/core/java/com/android/server/am/InstrumentationReporter.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.app.IInstrumentationWatcher;
+import android.content.ComponentName;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import java.util.ArrayList;
+
+public class InstrumentationReporter {
+    static final boolean DEBUG = false;
+    static final String TAG = ActivityManagerDebugConfig.TAG_AM;
+
+    static final int REPORT_TYPE_STATUS = 0;
+    static final int REPORT_TYPE_FINISHED = 1;
+
+    final Object mLock = new Object();
+    ArrayList<Report> mPendingReports;
+    Thread mThread;
+
+    final class MyThread extends Thread {
+        public MyThread() {
+            super("InstrumentationReporter");
+            if (DEBUG) Slog.d(TAG, "Starting InstrumentationReporter: " + this);
+        }
+
+        @Override
+        public void run() {
+            Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
+            boolean waited = false;
+            while (true) {
+                ArrayList<Report> reports;
+                synchronized (mLock) {
+                    reports = mPendingReports;
+                    mPendingReports = null;
+                    if (reports == null || reports.isEmpty()) {
+                        if (!waited) {
+                            // Sleep for a little bit, to avoid thrashing through threads.
+                            try {
+                                mLock.wait(10000); // 10 seconds
+                            } catch (InterruptedException e) {
+                            }
+                            waited = true;
+                            continue;
+                        } else {
+                            mThread = null;
+                            if (DEBUG) Slog.d(TAG, "Exiting InstrumentationReporter: " + this);
+                            return;
+                        }
+                    }
+                }
+
+                waited = false;
+
+                for (int i=0; i<reports.size(); i++) {
+                    final Report rep = reports.get(i);
+                    try {
+                        if (rep.mType == REPORT_TYPE_STATUS) {
+                            if (DEBUG) Slog.d(TAG, "Dispatch status to " + rep.mWatcher
+                                    + ": " + rep.mName.flattenToShortString()
+                                    + " code=" + rep.mResultCode + " result=" + rep.mResults);
+                            rep.mWatcher.instrumentationStatus(rep.mName, rep.mResultCode,
+                                    rep.mResults);
+                        } else {
+                            if (DEBUG) Slog.d(TAG, "Dispatch finished to " + rep.mWatcher
+                                    + ": " + rep.mName.flattenToShortString()
+                                    + " code=" + rep.mResultCode + " result=" + rep.mResults);
+                            rep.mWatcher.instrumentationFinished(rep.mName, rep.mResultCode,
+                                    rep.mResults);
+                        }
+                    } catch (RemoteException e) {
+                        Slog.i(TAG, "Failure reporting to instrumentation watcher: comp="
+                                + rep.mName + " results=" + rep.mResults);
+                    }
+                }
+            }
+        }
+    }
+
+    final class Report {
+        final int mType;
+        final IInstrumentationWatcher mWatcher;
+        final ComponentName mName;
+        final int mResultCode;
+        final Bundle mResults;
+
+        Report(int type, IInstrumentationWatcher watcher, ComponentName name, int resultCode,
+                Bundle results) {
+            mType = type;
+            mWatcher = watcher;
+            mName = name;
+            mResultCode = resultCode;
+            mResults = results;
+        }
+    }
+
+    public void reportStatus(IInstrumentationWatcher watcher, ComponentName name, int resultCode,
+            Bundle results) {
+        if (DEBUG) Slog.d(TAG, "Report status to " + watcher
+                + ": " + name.flattenToShortString()
+                + " code=" + resultCode + " result=" + results);
+        report(new Report(REPORT_TYPE_STATUS, watcher, name, resultCode, results));
+    }
+
+    public void reportFinished(IInstrumentationWatcher watcher, ComponentName name, int resultCode,
+            Bundle results) {
+        if (DEBUG) Slog.d(TAG, "Report finished to " + watcher
+                + ": " + name.flattenToShortString()
+                + " code=" + resultCode + " result=" + results);
+        report(new Report(REPORT_TYPE_FINISHED, watcher, name, resultCode, results));
+    }
+
+    private void report(Report report) {
+        synchronized (mLock) {
+            if (mThread == null) {
+                mThread = new MyThread();
+                mThread.start();
+            }
+            if (mPendingReports == null) {
+                mPendingReports = new ArrayList<>();
+            }
+            mPendingReports.add(report);
+            mLock.notifyAll();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/am/ProcessStartLogger.java b/services/core/java/com/android/server/am/ProcessStartLogger.java
index d2aa966..39fbeb5 100644
--- a/services/core/java/com/android/server/am/ProcessStartLogger.java
+++ b/services/core/java/com/android/server/am/ProcessStartLogger.java
@@ -4,7 +4,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
 import android.app.AppGlobals;
-import android.auditing.SecurityLog;
+import android.app.admin.SecurityLog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index ea85fa1..4eae45c 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -759,6 +759,14 @@
         if (r.isPersistable()) {
             mService.notifyTaskPersisterLocked(this, false);
         }
+
+        if (stack != null && stack.mStackId == PINNED_STACK_ID) {
+            // We normally notify listeners of task stack changes on pause, however pinned stack
+            // activities are normally in the paused state so no notification will be sent there
+            // before the activity is removed. We send it here so instead.
+            mService.notifyTaskStackChangedLocked();
+        }
+
         if (mActivities.isEmpty()) {
             return !mReuseTask;
         }
@@ -1334,8 +1342,13 @@
         if (bounds == null) {
             return;
         }
-        final int minimalSize = mMinimalSize == -1
-                ? mService.mStackSupervisor.mDefaultMinimalSizeOfResizeableTask : mMinimalSize;
+        int minimalSize = mMinimalSize;
+        // If the task has no requested minimal size, we'd like to enforce a minimal size
+        // so that the user can not render the task too small to manipulate. We don't need
+        // to do this for the pinned stack as the bounds are controlled by the system.
+        if (minimalSize == -1 && stack.mStackId != PINNED_STACK_ID) {
+            minimalSize = mService.mStackSupervisor.mDefaultMinimalSizeOfResizeableTask;
+        }
         final boolean adjustWidth = minimalSize > bounds.width();
         final boolean adjustHeight = minimalSize > bounds.height();
         if (!(adjustWidth || adjustHeight)) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d919737..5320221 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -28,6 +28,7 @@
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.NotificationManager;
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
@@ -40,6 +41,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
@@ -105,9 +107,6 @@
 import android.util.Slog;
 import android.util.SparseIntArray;
 import android.view.KeyEvent;
-import android.view.OrientationEventListener;
-import android.view.Surface;
-import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
 
 import com.android.internal.util.XmlUtils;
@@ -206,7 +205,6 @@
     private static final int MSG_SET_FORCE_USE = 8;
     private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
     private static final int MSG_SET_ALL_VOLUMES = 10;
-    private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 11;
     private static final int MSG_REPORT_NEW_ROUTES = 12;
     private static final int MSG_SET_FORCE_BT_A2DP_USE = 13;
     private static final int MSG_CHECK_MUSIC_ACTIVE = 14;
@@ -218,7 +216,6 @@
     private static final int MSG_UNLOAD_SOUND_EFFECTS = 20;
     private static final int MSG_SYSTEM_READY = 21;
     private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 22;
-    private static final int MSG_PERSIST_MICROPHONE_MUTE = 23;
     private static final int MSG_UNMUTE_STREAM = 24;
     private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 25;
     private static final int MSG_INDICATE_SYSTEM_READY = 26;
@@ -557,6 +554,7 @@
 
     private static Long mLastDeviceConnectMsgTime = new Long(0);
 
+    private NotificationManager mNm;
     private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate;
     private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT;
     private long mLoweredFromNormalToVibrateTime;
@@ -665,6 +663,7 @@
         // array initialized by updateStreamVolumeAlias()
         updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
         readPersistedSettings();
+        readUserRestrictions();
         mSettingsObserver = new SettingsObserver();
         createStreamStates();
 
@@ -751,6 +750,8 @@
             }
         }
 
+        mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+
         sendMsg(mAudioHandler,
                 MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
                 SENDMSG_REPLACE,
@@ -1109,35 +1110,6 @@
                 System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED,
                 UserHandle.USER_CURRENT);
 
-        final int currentUser = getCurrentUserId();
-
-        // In addition to checking the system setting, also check the current user restriction.
-        // Because of the delay before persisting VOLUME_MASTER_MUTE, there's a window where
-        // DISALLOW_ADJUST_VOLUME will be ignored when it's set right before switching users.
-        boolean masterMute = (System.getIntForUser(cr, System.VOLUME_MASTER_MUTE,
-                0, UserHandle.USER_CURRENT) == 1)
-                || mUserManagerInternal.getUserRestriction(
-                    currentUser, UserManager.DISALLOW_ADJUST_VOLUME);
-        if (mUseFixedVolume) {
-            masterMute = false;
-            AudioSystem.setMasterVolume(1.0f);
-        }
-        if (DEBUG_VOL) {
-            Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
-        }
-        setSystemAudioMute(masterMute);
-        AudioSystem.setMasterMute(masterMute);
-        broadcastMasterMuteStatus(masterMute);
-
-        boolean microphoneMute =
-                (System.getIntForUser(cr, System.MICROPHONE_MUTE, 0, UserHandle.USER_CURRENT) == 1)
-                || mUserManagerInternal.getUserRestriction(
-                        currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
-        if (DEBUG_VOL) {
-            Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
-        }
-        AudioSystem.muteMicrophone(microphoneMute);
-
         updateMasterMono(cr);
 
         // Each stream will read its own persisted settings
@@ -1154,6 +1126,31 @@
         mVolumeController.loadSettings(cr);
     }
 
+    private void readUserRestrictions() {
+        final int currentUser = getCurrentUserId();
+
+        // Check the current user restriction.
+        boolean masterMute = mUserManagerInternal.getUserRestriction(
+                    currentUser, UserManager.DISALLOW_ADJUST_VOLUME);
+        if (mUseFixedVolume) {
+            masterMute = false;
+            AudioSystem.setMasterVolume(1.0f);
+        }
+        if (DEBUG_VOL) {
+            Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
+        }
+        setSystemAudioMute(masterMute);
+        AudioSystem.setMasterMute(masterMute);
+        broadcastMasterMuteStatus(masterMute);
+
+        boolean microphoneMute = mUserManagerInternal.getUserRestriction(
+                currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
+        if (DEBUG_VOL) {
+            Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
+        }
+        AudioSystem.muteMicrophone(microphoneMute);
+    }
+
     private int rescaleIndex(int index, int srcStream, int dstStream) {
         return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex();
     }
@@ -1293,7 +1290,7 @@
             // Check if the ringer mode handles this adjustment. If it does we don't
             // need to adjust the volume further.
             final int result = checkForRingerModeChange(aliasIndex, direction, step,
-                    streamState.mIsMuted);
+                    streamState.mIsMuted, caller);
             adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
             // If suppressing a volume adjustment in silent mode, display the UI hint
             if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
@@ -1309,7 +1306,6 @@
                 && (mRingerModeMutedStreams & (1 << AudioSystem.STREAM_MUSIC)) != 0) {
             adjustVolume = false;
         }
-
         int oldIndex = mStreamStates[streamType].getIndex(device);
 
         if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
@@ -1453,10 +1449,7 @@
         }
     };
 
-    private void onSetStreamVolume(int streamType, int index, int flags, int device,
-            String caller) {
-        final int stream = mStreamVolumeAlias[streamType];
-        setStreamVolumeInt(stream, index, device, false, caller);
+    private int getNewRingerMode(int stream, int index, int flags) {
         // setting volume on ui sounds stream type also controls silent mode
         if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
                 (stream == getUiSoundsStreamType())) {
@@ -1464,11 +1457,49 @@
             if (index == 0) {
                 newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
                         : mVolumePolicy.volumeDownToEnterSilent ? AudioManager.RINGER_MODE_SILENT
-                        : AudioManager.RINGER_MODE_NORMAL;
+                                : AudioManager.RINGER_MODE_NORMAL;
             } else {
                 newRingerMode = AudioManager.RINGER_MODE_NORMAL;
             }
-            setRingerMode(newRingerMode, TAG + ".onSetStreamVolume", false /*external*/);
+            return newRingerMode;
+        }
+        return getRingerModeExternal();
+    }
+
+    private boolean isAndroidNPlus(String caller) {
+        try {
+            final ApplicationInfo applicationInfo =
+                    mContext.getPackageManager().getApplicationInfoAsUser(
+                            caller, 0, UserHandle.getUserId(Binder.getCallingUid()));
+            if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
+                return true;
+            }
+            return false;
+        } catch (PackageManager.NameNotFoundException e) {
+            return true;
+        }
+    }
+
+    private boolean wouldToggleZenMode(int newMode) {
+        if (getRingerModeExternal() == AudioManager.RINGER_MODE_SILENT
+                && newMode != AudioManager.RINGER_MODE_SILENT) {
+            return true;
+        } else if (getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT
+                && newMode == AudioManager.RINGER_MODE_SILENT) {
+            return true;
+        }
+        return false;
+    }
+
+    private void onSetStreamVolume(int streamType, int index, int flags, int device,
+            String caller) {
+        final int stream = mStreamVolumeAlias[streamType];
+        setStreamVolumeInt(stream, index, device, false, caller);
+        // setting volume on ui sounds stream type also controls silent mode
+        if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
+                (stream == getUiSoundsStreamType())) {
+            setRingerMode(getNewRingerMode(stream, index, flags),
+                    TAG + ".onSetStreamVolume", false /*external*/);
         }
         // setting non-zero volume for a muted stream unmutes the stream and vice versa
         mStreamStates[stream].mute(index == 0);
@@ -1509,6 +1540,12 @@
             return;
         }
 
+        if (isAndroidNPlus(callingPackage)
+                && wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags))
+                && !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) {
+            throw new SecurityException("Not allowed to change Do Not Disturb state");
+        }
+
         synchronized (mSafeMediaVolumeState) {
             // reset any pending volume command
             mPendingVolumeCommand = null;
@@ -1869,20 +1906,12 @@
             if (mute != AudioSystem.getMasterMute()) {
                 setSystemAudioMute(mute);
                 AudioSystem.setMasterMute(mute);
-                // Post a persist master volume msg
-                sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1
-                        : 0, userId, null, PERSIST_DELAY);
                 sendMasterMuteUpdate(mute, flags);
 
                 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
                 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
                 sendBroadcastToAll(intent);
             }
-        } else {
-            // If not the current user just persist the setting which will be loaded
-            // on user switch.
-            sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1
-                    : 0, userId, null, PERSIST_DELAY);
         }
     }
 
@@ -1975,8 +2004,6 @@
             AudioSystem.muteMicrophone(on);
         }
         // Post a persist microphone msg.
-        sendMsg(mAudioHandler, MSG_PERSIST_MICROPHONE_MUTE, SENDMSG_REPLACE, on ? 1
-                : 0, userId, null, PERSIST_DELAY);
     }
 
     @Override
@@ -2005,6 +2032,11 @@
     }
 
     public void setRingerModeExternal(int ringerMode, String caller) {
+        if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
+                && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
+            throw new SecurityException("Not allowed to change Do Not Disturb state");
+        }
+
         setRingerMode(ringerMode, caller, true /*external*/);
     }
 
@@ -2560,6 +2592,7 @@
     private void readAudioSettings(boolean userSwitch) {
         // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
         readPersistedSettings();
+        readUserRestrictions();
 
         // restore volume settings
         int numStreamTypes = AudioSystem.getNumStreamTypes();
@@ -3328,7 +3361,8 @@
      * adjusting volume. If so, this will set the proper ringer mode and volume
      * indices on the stream states.
      */
-    private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted) {
+    private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
+            String caller) {
         final boolean isTv = mPlatformType == AudioSystem.PLATFORM_TELEVISION;
         int result = FLAG_ADJUST_VOLUME;
         int ringerMode = getRingerModeInternal();
@@ -3417,6 +3451,11 @@
             break;
         }
 
+        if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
+                && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
+            throw new SecurityException("Not allowed to change Do Not Disturb state");
+        }
+
         setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
 
         mPrevVolDirection = direction;
@@ -4492,16 +4531,6 @@
                     persistVolume((VolumeStreamState) msg.obj, msg.arg1);
                     break;
 
-                case MSG_PERSIST_MASTER_VOLUME_MUTE:
-                    if (mUseFixedVolume) {
-                        return;
-                    }
-                    Settings.System.putIntForUser(mContentResolver,
-                                                 Settings.System.VOLUME_MASTER_MUTE,
-                                                 msg.arg1,
-                                                 msg.arg2);
-                    break;
-
                 case MSG_PERSIST_RINGER_MODE:
                     // note that the value persisted is the current ringer mode, not the
                     // value of ringer mode as of the time the request was made to persist
@@ -4624,15 +4653,11 @@
                             Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
                             UserHandle.USER_CURRENT);
                     break;
-                case MSG_PERSIST_MICROPHONE_MUTE:
-                    Settings.System.putIntForUser(mContentResolver,
-                                                 Settings.System.MICROPHONE_MUTE,
-                                                 msg.arg1,
-                                                 msg.arg2);
-                    break;
+
                 case MSG_UNMUTE_STREAM:
                     onUnmuteStream(msg.arg1, msg.arg2);
                     break;
+
                 case MSG_DYN_POLICY_MIX_STATE_UPDATE:
                     onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
                     break;
diff --git a/services/core/java/com/android/server/connectivity/ApfFilter.java b/services/core/java/com/android/server/connectivity/ApfFilter.java
index 25c84e1..8195319 100644
--- a/services/core/java/com/android/server/connectivity/ApfFilter.java
+++ b/services/core/java/com/android/server/connectivity/ApfFilter.java
@@ -29,14 +29,19 @@
 import android.util.Pair;
 
 import com.android.internal.util.HexDump;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.ConnectivityService;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.lang.Thread;
+import java.net.Inet6Address;
+import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
+import java.net.UnknownHostException;
 import java.nio.ByteBuffer;
+import java.nio.BufferUnderflowException;
 import java.util.ArrayList;
 import java.util.Arrays;
 
@@ -85,6 +90,7 @@
     }
 
     private static final String TAG = "ApfFilter";
+    private static final boolean VDBG = true;
 
     private final ConnectivityService mConnectivityService;
     private final NetworkAgentInfo mNai;
@@ -152,9 +158,14 @@
         private static final int ETH_HEADER_LEN = 14;
 
         private static final int IPV6_HEADER_LEN = 40;
+        private static final int IPV6_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 8;
+        private static final int IPV6_DST_ADDR_OFFSET = ETH_HEADER_LEN + 24;
 
         // From RFC4861:
         private static final int ICMP6_RA_HEADER_LEN = 16;
+        private static final int ICMP6_RA_CHECKSUM_OFFSET =
+                ETH_HEADER_LEN + IPV6_HEADER_LEN + 2;
+        private static final int ICMP6_RA_CHECKSUM_LEN = 2;
         private static final int ICMP6_RA_OPTION_OFFSET =
                 ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
         private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
@@ -189,6 +200,66 @@
         // When the packet was last captured, in seconds since Unix Epoch
         long mLastSeen;
 
+        // For debugging only. Offsets into the packet where PIOs are.
+        private final ArrayList<Integer> mPrefixOptionOffsets;
+        // For debugging only. How many times this RA was seen.
+        int seenCount = 0;
+
+
+        private String IPv6AddresstoString(int pos) {
+            try {
+                byte[] array = mPacket.array();
+                // Can't just call copyOfRange() and see if it throws, because if it reads past the
+                // end it pads with zeros instead of throwing.
+                if (pos < 0 || pos + 16 > array.length || pos + 16 < pos) {
+                    return "???";
+                }
+                byte[] addressBytes = Arrays.copyOfRange(array, pos, pos + 16);
+                InetAddress address = (Inet6Address) InetAddress.getByAddress(addressBytes);
+                return address.getHostAddress();
+            } catch (UnsupportedOperationException e) {
+                // array() failed. Cannot happen, mPacket is array-backed and read-write.
+                return "???";
+            } catch (ClassCastException | UnknownHostException e) {
+                // Cannot happen.
+                return "???";
+            }
+        }
+
+        // Can't be static because it's in a non-static inner class.
+        // TODO: Make this final once RA is its own class.
+        private int uint8(byte b) {
+            return b & 0xff;
+        }
+
+        private int uint16(short s) {
+            return s & 0xffff;
+        }
+
+        private long uint32(int s) {
+            return s & 0xffffffff;
+        }
+
+        public String toString() {
+            try {
+                StringBuffer sb = new StringBuffer();
+                sb.append(String.format("RA %s -> %s %d ",
+                        IPv6AddresstoString(IPV6_SRC_ADDR_OFFSET),
+                        IPv6AddresstoString(IPV6_DST_ADDR_OFFSET),
+                        uint16(mPacket.getShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET))));
+                for (int i: mPrefixOptionOffsets) {
+                    String prefix = IPv6AddresstoString(i + 16);
+                    int length = uint8(mPacket.get(i + 2));
+                    long valid = mPacket.getInt(i + 4);
+                    long preferred = mPacket.getInt(i + 8);
+                    sb.append(String.format("%s/%d %d/%d ", prefix, length, valid, preferred));
+                }
+                return sb.toString();
+            } catch (BufferUnderflowException | IndexOutOfBoundsException e) {
+                return "<Malformed RA>";
+            }
+        }
+
         /**
          * Add a binary range of the packet that does not include a lifetime to mNonLifetimes.
          * Assumes mPacket.position() is as far as we've parsed the packet.
@@ -216,10 +287,18 @@
             mPacket.clear();
             mLastSeen = curTime();
 
+            // Ignore the checksum.
+            int lastNonLifetimeStart = addNonLifetime(0,
+                    ICMP6_RA_CHECKSUM_OFFSET,
+                    ICMP6_RA_CHECKSUM_LEN);
+
             // Parse router lifetime
-            int lastNonLifetimeStart = addNonLifetime(0, ICMP6_RA_ROUTER_LIFETIME_OFFSET,
+            lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
+                    ICMP6_RA_ROUTER_LIFETIME_OFFSET,
                     ICMP6_RA_ROUTER_LIFETIME_LEN);
+
             // Parse ICMP6 options
+            mPrefixOptionOffsets = new ArrayList<>();
             mPacket.position(ICMP6_RA_OPTION_OFFSET);
             while (mPacket.hasRemaining()) {
                 int optionType = ((int)mPacket.get(mPacket.position())) & 0xff;
@@ -234,6 +313,7 @@
                         lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
                                 ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
                                 ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN);
+                        mPrefixOptionOffsets.add(mPacket.position());
                         break;
                     // These three options have the same lifetime offset and size, so process
                     // together:
@@ -282,6 +362,12 @@
             ByteBuffer byteBuffer = ByteBuffer.wrap(packet);
             for (int i = 0; (i + 1) < mNonLifetimes.size(); i++) {
                 int offset = mNonLifetimes.get(i).first + mNonLifetimes.get(i).second;
+
+                // The checksum is in mNonLifetimes, but it's not a lifetime.
+                if (offset == ICMP6_RA_CHECKSUM_OFFSET) {
+                     continue;
+                }
+
                 int lifetimeLength = mNonLifetimes.get(i+1).first - offset;
                 long val;
                 switch (lifetimeLength) {
@@ -329,6 +415,10 @@
                 if ((i + 1) < mNonLifetimes.size()) {
                     Pair<Integer, Integer> nextNonLifetime = mNonLifetimes.get(i + 1);
                     int offset = nonLifetime.first + nonLifetime.second;
+                    // Skip the checksum.
+                    if (offset == ICMP6_RA_CHECKSUM_OFFSET) {
+                        continue;
+                    }
                     int length = nextNonLifetime.first - offset;
                     switch (length) {
                         case 4: gen.addLoad32(Register.R0, offset); break;
@@ -363,6 +453,9 @@
     // How long should the last installed filter program live for? In seconds.
     private long mLastInstalledProgramMinLifetime;
 
+    // For debugging only. The length in bytes of the last program.
+    private long mLastInstalledProgramLength;
+
     private void installNewProgram() {
         if (mRas.size() == 0) return;
         final byte[] program;
@@ -402,7 +495,12 @@
         }
         mLastTimeInstalledProgram = curTime();
         mLastInstalledProgramMinLifetime = programMinLifetime;
-        hexDump("Installing filter: ", program, program.length);
+        mLastInstalledProgramLength = program.length;
+        if (VDBG) {
+            hexDump("Installing filter: ", program, program.length);
+        } else {
+            Log.d(TAG, "Installing filter length=" + program.length);
+        }
         mConnectivityService.pushApfProgramToNetwork(mNai, program);
     }
 
@@ -421,16 +519,17 @@
     }
 
     private void processRa(byte[] packet, int length) {
-        hexDump("Read packet = ", packet, length);
+        if (VDBG) hexDump("Read packet = ", packet, length);
 
         // Have we seen this RA before?
         for (int i = 0; i < mRas.size(); i++) {
             Ra ra = mRas.get(i);
             if (ra.matches(packet, length)) {
-                log("matched RA");
+                if (VDBG) log("matched RA " + ra);
                 // Update lifetimes.
                 ra.mLastSeen = curTime();
                 ra.mMinLifetime = ra.minLifetime(packet, length);
+                ra.seenCount++;
 
                 // Keep mRas in LRU order so as to prioritize generating filters for recently seen
                 // RAs. LRU prioritizes this because RA filters are generated in order from mRas
@@ -448,7 +547,7 @@
         // Purge expired RAs.
         for (int i = 0; i < mRas.size();) {
             if (mRas.get(i).isExpired()) {
-                log("expired RA");
+                log("Expired RA " + mRas.get(i));
                 mRas.remove(i);
             } else {
                 i++;
@@ -457,8 +556,9 @@
         // TODO: figure out how to proceed when we've received more then MAX_RAS RAs.
         if (mRas.size() >= MAX_RAS) return;
         try {
-            log("adding RA");
-            mRas.add(new Ra(packet, length));
+            Ra ra = new Ra(packet, length);
+            log("Adding " + ra);
+            mRas.add(ra);
         } catch (Exception e) {
             Log.e(TAG, "Error parsing RA: " + e);
             return;
@@ -473,8 +573,8 @@
     public static void maybeInstall(ConnectivityService connectivityService, NetworkAgentInfo nai) {
         if (nai.networkMisc == null) return;
         if (nai.networkMisc.apfVersionSupported == 0) return;
-        if (nai.networkMisc.maximumApfProgramSize < 200) {
-            Log.e(TAG, "Uselessly small APF size limit: " + nai.networkMisc.maximumApfProgramSize);
+        if (nai.networkMisc.maximumApfProgramSize < 512) {
+            Log.e(TAG, "Unacceptably small APF limit: " + nai.networkMisc.maximumApfProgramSize);
             return;
         }
         // For now only support generating programs for Ethernet frames. If this restriction is
@@ -491,9 +591,35 @@
 
     public void shutdown() {
         if (mReceiveThread != null) {
-            log("shuting down");
+            log("shutting down");
             mReceiveThread.halt();  // Also closes socket.
             mReceiveThread = null;
         }
     }
+
+    public void dump(IndentingPrintWriter pw) {
+        pw.println("APF version: " + mNai.networkMisc.apfVersionSupported);
+        pw.println("Max program size: " + mNai.networkMisc.maximumApfProgramSize);
+        pw.println("Receive thread: " + (mReceiveThread != null ? "RUNNING" : "STOPPED"));
+        if (mLastTimeInstalledProgram == 0) {
+            pw.println("No program installed.");
+            return;
+        }
+
+        pw.println(String.format(
+                "Last program length %d, installed %ds ago, lifetime %d",
+                mLastInstalledProgramLength, curTime() - mLastTimeInstalledProgram,
+                mLastInstalledProgramMinLifetime));
+
+        pw.println("RA filters:");
+        pw.increaseIndent();
+        for (Ra ra: mRas) {
+            pw.println(ra);
+            pw.increaseIndent();
+            pw.println(String.format(
+                    "Seen: %d, last %ds ago", ra.seenCount, curTime() - ra.mLastSeen));
+            pw.decreaseIndent();
+        }
+        pw.decreaseIndent();
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 73da427..bce7733 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -688,12 +688,11 @@
             // Time how long it takes to get a response to our request
             long requestTimestamp = SystemClock.elapsedRealtime();
 
-            urlConnection.getInputStream();
+            httpResponseCode = urlConnection.getResponseCode();
 
             // Time how long it takes to get a response to our request
             long responseTimestamp = SystemClock.elapsedRealtime();
 
-            httpResponseCode = urlConnection.getResponseCode();
             validationLog("isCaptivePortal: ret=" + httpResponseCode +
                     " headers=" + urlConnection.getHeaderFields());
             // NOTE: We may want to consider an "HTTP/1.0 204" response to be a captive
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 212e077..03191a0 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -18,12 +18,16 @@
 
 import android.Manifest;
 import android.accounts.Account;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.IContentService;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.ISyncStatusObserver;
 import android.content.PeriodicSync;
 import android.content.SyncAdapterType;
@@ -32,6 +36,7 @@
 import android.content.SyncStatusInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
+import android.content.pm.ProviderInfo;
 import android.database.IContentObserver;
 import android.database.sqlite.SQLiteException;
 import android.net.Uri;
@@ -44,30 +49,64 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Log;
+import android.util.Pair;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.SparseIntArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.security.InvalidParameterException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * {@hide}
  */
 public final class ContentService extends IContentService.Stub {
     private static final String TAG = "ContentService";
+
     private Context mContext;
     private boolean mFactoryTest;
+
     private final ObserverNode mRootNode = new ObserverNode("");
+
     private SyncManager mSyncManager = null;
     private final Object mSyncManagerLock = new Object();
 
+    /**
+     * Map from userId to providerPackageName to [clientPackageName, uri] to
+     * value. This structure is carefully optimized to keep invalidation logic
+     * as cheap as possible.
+     */
+    @GuardedBy("mCache")
+    private final SparseArray<ArrayMap<String, ArrayMap<Pair<String, Uri>, Bundle>>>
+            mCache = new SparseArray<>();
+
+    private BroadcastReceiver mCacheReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final Uri data = intent.getData();
+            if (data != null) {
+                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+                        UserHandle.USER_NULL);
+                final String packageName = data.getSchemeSpecificPart();
+                invalidateCacheLocked(userId, packageName, null);
+            }
+        }
+    };
+
     private SyncManager getSyncManager() {
         if (SystemProperties.getBoolean("config.disable_network", false)) {
             return null;
@@ -85,13 +124,15 @@
     }
 
     @Override
-    protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    protected synchronized void dump(FileDescriptor fd, PrintWriter pw_, String[] args) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP,
                 "caller doesn't have the DUMP permission");
 
+        final IndentingPrintWriter pw = new IndentingPrintWriter(pw_, "  ");
+
         // This makes it so that future permission checks will be in the context of this
         // process rather than the caller's process. We will restore this before returning.
-        long identityToken = clearCallingIdentity();
+        final long identityToken = clearCallingIdentity();
         try {
             if (mSyncManager == null) {
                 pw.println("No SyncManager created!  (Disk full?)");
@@ -132,6 +173,19 @@
                 pw.print(" Total number of nodes: "); pw.println(counts[0]);
                 pw.print(" Total number of observers: "); pw.println(counts[1]);
             }
+
+            synchronized (mCache) {
+                pw.println();
+                pw.println("Cached content:");
+                pw.increaseIndent();
+                for (int i = 0; i < mCache.size(); i++) {
+                    pw.println("User " + mCache.keyAt(i) + ":");
+                    pw.increaseIndent();
+                    pw.println(mCache.valueAt(i));
+                    pw.decreaseIndent();
+                }
+                pw.decreaseIndent();
+            }
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -167,6 +221,15 @@
                         return getSyncAdapterPackagesForAuthorityAsUser(authority, userId);
                     }
                 });
+
+        final IntentFilter packageFilter = new IntentFilter();
+        packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
+        packageFilter.addDataScheme("package");
+        mContext.registerReceiverAsUser(mCacheReceiver, UserHandle.ALL,
+                packageFilter, null, null);
     }
 
     public void systemReady() {
@@ -312,6 +375,11 @@
                             uri.getAuthority());
                 }
             }
+
+            synchronized (mCache) {
+                final String providerPackageName = getProviderPackageName(uri);
+                invalidateCacheLocked(userHandle, providerPackageName, uri);
+            }
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -915,6 +983,86 @@
         }
     }
 
+    private @Nullable String getProviderPackageName(Uri uri) {
+        final ProviderInfo pi = mContext.getPackageManager()
+                .resolveContentProvider(uri.getAuthority(), 0);
+        return (pi != null) ? pi.packageName : null;
+    }
+
+    private ArrayMap<Pair<String, Uri>, Bundle> findOrCreateCacheLocked(int userId,
+            String providerPackageName) {
+        ArrayMap<String, ArrayMap<Pair<String, Uri>, Bundle>> userCache = mCache.get(userId);
+        if (userCache == null) {
+            userCache = new ArrayMap<>();
+            mCache.put(userId, userCache);
+        }
+        ArrayMap<Pair<String, Uri>, Bundle> packageCache = userCache.get(providerPackageName);
+        if (packageCache == null) {
+            packageCache = new ArrayMap<>();
+            userCache.put(providerPackageName, packageCache);
+        }
+        return packageCache;
+    }
+
+    private void invalidateCacheLocked(int userId, String providerPackageName, Uri uri) {
+        ArrayMap<String, ArrayMap<Pair<String, Uri>, Bundle>> userCache = mCache.get(userId);
+        if (userCache == null) return;
+
+        ArrayMap<Pair<String, Uri>, Bundle> packageCache = userCache.get(providerPackageName);
+        if (packageCache == null) return;
+
+        if (uri != null) {
+            for (int i = 0; i < packageCache.size();) {
+                final Uri key = packageCache.keyAt(i).second;
+                if (Objects.equals(key, uri)) {
+                    packageCache.removeAt(i);
+                } else {
+                    i++;
+                }
+            }
+        } else {
+            packageCache.clear();
+        }
+    }
+
+    @Override
+    public void putCache(String packageName, Uri key, Bundle value, int userId) {
+        enforceCrossUserPermission(userId, TAG);
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CACHE_CONTENT, TAG);
+        mContext.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(),
+                packageName);
+
+        final String providerPackageName = getProviderPackageName(key);
+        final Pair<String, Uri> fullKey = Pair.create(packageName, key);
+
+        synchronized (mCache) {
+            final ArrayMap<Pair<String, Uri>, Bundle> cache = findOrCreateCacheLocked(userId,
+                    providerPackageName);
+            if (value != null) {
+                cache.put(fullKey, value);
+            } else {
+                cache.remove(fullKey);
+            }
+        }
+    }
+
+    @Override
+    public Bundle getCache(String packageName, Uri key, int userId) {
+        enforceCrossUserPermission(userId, TAG);
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CACHE_CONTENT, TAG);
+        mContext.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(),
+                packageName);
+
+        final String providerPackageName = getProviderPackageName(key);
+        final Pair<String, Uri> fullKey = Pair.create(packageName, key);
+
+        synchronized (mCache) {
+            final ArrayMap<Pair<String, Uri>, Bundle> cache = findOrCreateCacheLocked(userId,
+                    providerPackageName);
+            return cache.get(fullKey);
+        }
+    }
+
     public static ContentService main(Context context, boolean factoryTest) {
         ContentService service = new ContentService(context, factoryTest);
         ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service);
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 95a9875..e5342ce 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -78,8 +78,9 @@
 import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
-import android.util.SparseArray;
 
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerInternal;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
@@ -113,9 +114,7 @@
  * All scheduled syncs will be passed on to JobScheduler as jobs
  * (See {@link #scheduleSyncOperationH(SyncOperation, long)}. This function schedules a job
  * with JobScheduler with appropriate delay and constraints (according to backoffs and extras).
- * A local copy of each scheduled SyncOperation object is stored in {@link mScheduledSyncs}.This
- * acts as a cache, so that we don't have to query JobScheduler every time we want to get a list of
- * all scheduled operations. The scheduleSyncOperationH function also assigns a unique jobId to each
+ * The scheduleSyncOperationH function also assigns a unique jobId to each
  * SyncOperation.
  *
  * Periodic Syncs:
@@ -129,14 +128,6 @@
  * run at a later time. Similarly, when a sync succeeds, backoff is cleared and all associated syncs
  * are rescheduled. A rescheduled sync will get a new jobId.
  *
- * State of {@link mScheduledSyncs}:
- * Every one-off SyncOperation will be put into this SparseArray when it is scheduled with
- * JobScheduler. And it will be removed once JobScheduler has started the job. Periodic syncs work
- * differently. They will always be present in mScheduledSyncs until the periodic sync is removed.
- * This is to ensure that if a request to add a periodic sync comes in, we add a new one only if a
- * duplicate doesn't exist. At every point of time, mScheduledSyncs and JobScheduler will show the
- * same pending syncs.
- *
  * @hide
  */
 public class SyncManager {
@@ -192,6 +183,13 @@
      */
     private static final long SYNC_DELAY_ON_CONFLICT = 10*1000; // 10 seconds
 
+    /**
+     * Generate job ids in the range [MIN_SYNC_JOB_ID, MAX_SYNC_JOB_ID) to avoid conflicts with
+     * other jobs scheduled by the system process.
+     */
+    private static final int MIN_SYNC_JOB_ID = 100000;
+    private static final int MAX_SYNC_JOB_ID = 110000;
+
     private static final String SYNC_WAKE_LOCK_PREFIX = "*sync*/";
     private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarm";
     private static final String SYNC_LOOP_WAKE_LOCK = "SyncLoopWakeLock";
@@ -213,6 +211,7 @@
     private final NotificationManager mNotificationMgr;
     private final IBatteryStats mBatteryStats;
     private JobScheduler mJobScheduler;
+    private JobSchedulerInternal mJobSchedulerInternal;
     private SyncJobService mSyncJobService;
 
     private SyncStorageEngine mSyncStorageEngine;
@@ -228,14 +227,13 @@
 
     protected SyncAdaptersCache mSyncAdapters;
 
-    // Cache of all operations scheduled on the JobScheduler so that JobScheduler doesn't have
-    // to be queried often.
-    private SparseArray<SyncOperation> mScheduledSyncs = new SparseArray<SyncOperation>(32);
     private final Random mRand;
 
-    private boolean isJobIdInUseLockedH(int jobId) {
-        if (mScheduledSyncs.indexOfKey(jobId) >= 0) {
-            return true;
+    private boolean isJobIdInUseLockedH(int jobId, List<JobInfo> pendingJobs) {
+        for (JobInfo job: pendingJobs) {
+            if (job.getId() == jobId) {
+                return true;
+            }
         }
         for (ActiveSyncContext asc: mActiveSyncContexts) {
             if (asc.mSyncOperation.jobId == jobId) {
@@ -246,35 +244,25 @@
     }
 
     private int getUnusedJobIdH() {
-        synchronized (mScheduledSyncs) {
-            int newJobId;
-            do {
-                newJobId = mRand.nextInt(Integer.MAX_VALUE);
-            } while (isJobIdInUseLockedH(newJobId));
-            return newJobId;
-        }
+        int newJobId;
+        do {
+            newJobId = MIN_SYNC_JOB_ID + mRand.nextInt(MAX_SYNC_JOB_ID - MIN_SYNC_JOB_ID);
+        } while (isJobIdInUseLockedH(newJobId,
+                mJobSchedulerInternal.getSystemScheduledPendingJobs()));
+        return newJobId;
     }
 
-    private void addSyncOperationToCache(SyncOperation op) {
-        synchronized (mScheduledSyncs) {
-            mScheduledSyncs.put(op.jobId, op);
-        }
-    }
-
-    private void removeSyncOperationFromCache(int jobId) {
-        synchronized (mScheduledSyncs) {
-            mScheduledSyncs.remove(jobId);
-        }
-    }
-
-    private List<SyncOperation> getAllPendingSyncsFromCache() {
-        synchronized (mScheduledSyncs) {
-            List<SyncOperation> pending = new ArrayList<SyncOperation>(mScheduledSyncs.size());
-            for (int i=0; i<mScheduledSyncs.size(); i++) {
-                pending.add(mScheduledSyncs.valueAt(i));
+    private List<SyncOperation> getAllPendingSyncs() {
+        verifyJobScheduler();
+        List<JobInfo> pendingJobs = mJobSchedulerInternal.getSystemScheduledPendingJobs();
+        List<SyncOperation> pendingSyncs = new ArrayList<SyncOperation>(pendingJobs.size());
+        for (JobInfo job: pendingJobs) {
+            SyncOperation op = SyncOperation.maybeCreateFromJobExtras(job.getExtras());
+            if (op != null) {
+                pendingSyncs.add(op);
             }
-            return pending;
         }
+        return pendingSyncs;
     }
 
     private final BroadcastReceiver mStorageIntentReceiver =
@@ -436,7 +424,7 @@
         mSyncHandler.postAtFrontOfQueue(new Runnable() {
             @Override
             public void run() {
-                List<SyncOperation> ops = getAllPendingSyncsFromCache();
+                List<SyncOperation> ops = getAllPendingSyncs();
                 Set<String> cleanedKeys = new HashSet<String>();
                 for (SyncOperation opx: ops) {
                     if (cleanedKeys.contains(opx.key)) {
@@ -448,7 +436,6 @@
                             continue;
                         }
                         if (opx.key.equals(opy.key)) {
-                            removeSyncOperationFromCache(opy.jobId);
                             mJobScheduler.cancel(opy.jobId);
                         }
                     }
@@ -466,18 +453,16 @@
         }
         mJobScheduler = (JobScheduler) mContext.getSystemService(
                 Context.JOB_SCHEDULER_SERVICE);
+        mJobSchedulerInternal = LocalServices.getService(JobSchedulerInternal.class);
         // Get all persisted syncs from JobScheduler
         List<JobInfo> pendingJobs = mJobScheduler.getAllPendingJobs();
-        synchronized (mScheduledSyncs) {
-            for (JobInfo job : pendingJobs) {
-                SyncOperation op = SyncOperation.maybeCreateFromJobExtras(job.getExtras());
-                if (op != null) {
-                    mScheduledSyncs.put(op.jobId, op);
-                    if (!op.isPeriodic) {
-                        // Set the pending status of this EndPoint to true. Pending icon is
-                        // shown on the settings activity.
-                        mSyncStorageEngine.markPending(op.target, true);
-                    }
+        for (JobInfo job : pendingJobs) {
+            SyncOperation op = SyncOperation.maybeCreateFromJobExtras(job.getExtras());
+            if (op != null) {
+                if (!op.isPeriodic) {
+                    // Set the pending status of this EndPoint to true. Pending icon is
+                    // shown on the settings activity.
+                    mSyncStorageEngine.markPending(op.target, true);
                 }
             }
         }
@@ -700,7 +685,7 @@
     }
 
     private void setAuthorityPendingState(EndPoint info) {
-        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<SyncOperation> ops = getAllPendingSyncs();
         for (SyncOperation op: ops) {
             if (!op.isPeriodic && op.target.matchesSpec(info)) {
                 getSyncStorageEngine().markPending(info, true);
@@ -920,11 +905,10 @@
 
     private void removeSyncsForAuthority(EndPoint info) {
         verifyJobScheduler();
-        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<SyncOperation> ops = getAllPendingSyncs();
         for (SyncOperation op: ops) {
             if (op.target.matchesSpec(info)) {
-                removeSyncOperationFromCache(op.jobId);
-                getJobScheduler().cancel(op.jobId);
+                 getJobScheduler().cancel(op.jobId);
             }
         }
     }
@@ -954,7 +938,7 @@
      * Get a list of periodic syncs corresponding to the given target.
      */
     public List<PeriodicSync> getPeriodicSyncs(EndPoint target) {
-        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<SyncOperation> ops = getAllPendingSyncs();
         List<PeriodicSync> periodicSyncs = new ArrayList<PeriodicSync>();
 
         for (SyncOperation op: ops) {
@@ -1138,12 +1122,11 @@
      * to current backoff and delayUntil values of this EndPoint.
      */
     private void rescheduleSyncs(EndPoint target) {
-        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<SyncOperation> ops = getAllPendingSyncs();
         int count = 0;
         for (SyncOperation op: ops) {
             if (!op.isPeriodic && op.target.matchesSpec(target)) {
                 count++;
-                removeSyncOperationFromCache(op.jobId);
                 getJobScheduler().cancel(op.jobId);
                 postScheduleSyncMessage(op);
             }
@@ -1244,7 +1227,7 @@
             int duplicatesCount = 0;
             long now = SystemClock.elapsedRealtime();
             syncOperation.expectedRuntime = now + minDelay;
-            List<SyncOperation> pending = getAllPendingSyncsFromCache();
+            List<SyncOperation> pending = getAllPendingSyncs();
             SyncOperation opWithLeastExpectedRuntime = syncOperation;
             for (SyncOperation op : pending) {
                 if (op.isPeriodic) {
@@ -1269,7 +1252,6 @@
                         if (isLoggable) {
                             Slog.v(TAG, "Cancelling duplicate sync " + op);
                         }
-                        removeSyncOperationFromCache(op.jobId);
                         getJobScheduler().cancel(op.jobId);
                     }
                 }
@@ -1287,7 +1269,6 @@
         if (syncOperation.jobId == SyncOperation.NO_JOB_ID) {
             syncOperation.jobId = getUnusedJobIdH();
         }
-        addSyncOperationToCache(syncOperation);
 
         if (isLoggable) {
             Slog.v(TAG, "scheduling sync operation " + syncOperation.toString());
@@ -1328,10 +1309,9 @@
      * have null account/provider info to specify all accounts/providers.
      */
     public void clearScheduledSyncOperations(SyncStorageEngine.EndPoint info) {
-        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<SyncOperation> ops = getAllPendingSyncs();
         for (SyncOperation op: ops) {
             if (!op.isPeriodic && op.target.matchesSpec(info)) {
-                removeSyncOperationFromCache(op.jobId);
                 getJobScheduler().cancel(op.jobId);
                 getSyncStorageEngine().markPending(op.target, false);
             }
@@ -1346,11 +1326,10 @@
      * @param extras extras bundle to uniquely identify sync.
      */
     public void cancelScheduledSyncOperation(SyncStorageEngine.EndPoint info, Bundle extras) {
-        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<SyncOperation> ops = getAllPendingSyncs();
         for (SyncOperation op: ops) {
             if (!op.isPeriodic && op.target.matchesSpec(info)
                     && syncExtrasEquals(extras, op.extras, false)) {
-                removeSyncOperationFromCache(op.jobId);
                 getJobScheduler().cancel(op.jobId);
             }
         }
@@ -1459,10 +1438,9 @@
 
         // Clean up the storage engine database
         mSyncStorageEngine.doDatabaseCleanup(new Account[0], userId);
-        List<SyncOperation> ops = getAllPendingSyncsFromCache();
+        List<SyncOperation> ops = getAllPendingSyncs();
         for (SyncOperation op: ops) {
             if (op.target.userId == userId) {
-                removeSyncOperationFromCache(op.jobId);
                 getJobScheduler().cancel(op.jobId);
             }
         }
@@ -1628,7 +1606,7 @@
 
     protected void dumpPendingSyncs(PrintWriter pw) {
         pw.println("Pending Syncs:");
-        List<SyncOperation> pendingSyncs = getAllPendingSyncsFromCache();
+        List<SyncOperation> pendingSyncs = getAllPendingSyncs();
         int count = 0;
         for (SyncOperation op: pendingSyncs) {
             if (!op.isPeriodic) {
@@ -1642,7 +1620,7 @@
 
     protected void dumpPeriodicSyncs(PrintWriter pw) {
         pw.println("Periodic Syncs:");
-        List<SyncOperation> pendingSyncs = getAllPendingSyncsFromCache();
+        List<SyncOperation> pendingSyncs = getAllPendingSyncs();
         int count = 0;
         for (SyncOperation op: pendingSyncs) {
             if (op.isPeriodic) {
@@ -2252,10 +2230,6 @@
         private boolean tryEnqueueMessageUntilReadyToRun(Message msg) {
             synchronized (this) {
                 if (!mBootCompleted || !mProvisioned) {
-                    if (msg.what == MESSAGE_START_SYNC) {
-                        SyncOperation op = (SyncOperation) msg.obj;
-                        addSyncOperationToCache(op);
-                    }
                     // Need to copy the message bc looper will recycle it.
                     Message m = Message.obtain(msg);
                     mUnreadyQueue.add(m);
@@ -2472,7 +2446,6 @@
             if (op.isPeriodic) {
                 scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay);
             } else {
-                removeSyncOperationFromCache(op.jobId);
                 scheduleSyncOperationH(op, delay);
             }
         }
@@ -2482,7 +2455,6 @@
             if (op.isPeriodic) {
                 scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay);
             } else {
-                removeSyncOperationFromCache(op.jobId);
                 scheduleSyncOperationH(op, delay);
             }
         }
@@ -2508,7 +2480,7 @@
             if (op.isPeriodic) {
                 // Don't allow this periodic to run if a previous instance failed and is currently
                 // scheduled according to some backoff criteria.
-                List<SyncOperation> ops = getAllPendingSyncsFromCache();
+                List<SyncOperation> ops = getAllPendingSyncs();
                 for (SyncOperation syncOperation: ops) {
                     if (syncOperation.sourcePeriodicId == op.jobId) {
                         mSyncJobService.callJobFinished(op.jobId, false);
@@ -2528,9 +2500,6 @@
                     deferSyncH(op, 0 /* No minimum delay */);
                     return;
                 }
-            } else {
-                // Remove SyncOperation entry from mScheduledSyncs cache for non periodic jobs.
-                removeSyncOperationFromCache(op.jobId);
             }
 
             // Check for conflicting syncs.
@@ -2609,10 +2578,9 @@
                 }
             }
 
-            List<SyncOperation> ops = getAllPendingSyncsFromCache();
+            List<SyncOperation> ops = getAllPendingSyncs();
             for (SyncOperation op: ops) {
                 if (!containsAccountAndUser(accounts, op.target.account, op.target.userId)) {
-                    removeSyncOperationFromCache(op.jobId);
                     getJobScheduler().cancel(op.jobId);
                 }
             }
@@ -2658,7 +2626,7 @@
                         + " flexMillis: " + flex
                         + " extras: " + extras.toString());
             }
-            List<SyncOperation> ops = getAllPendingSyncsFromCache();
+            List<SyncOperation> ops = getAllPendingSyncs();
             for (SyncOperation op: ops) {
                 if (op.isPeriodic && op.target.matchesSpec(target)
                         && syncExtrasEquals(op.extras, extras, true /* includeSyncSettings */)) {
@@ -2697,7 +2665,7 @@
          */
         private void removePeriodicSyncInternalH(SyncOperation syncOperation) {
             // Remove this periodic sync and all one-off syncs initiated by it.
-            List<SyncOperation> ops = getAllPendingSyncsFromCache();
+            List<SyncOperation> ops = getAllPendingSyncs();
             for (SyncOperation op: ops) {
                 if (op.sourcePeriodicId == syncOperation.jobId || op.jobId == syncOperation.jobId) {
                     ActiveSyncContext asc = findActiveSyncContextH(syncOperation.jobId);
@@ -2705,7 +2673,6 @@
                         mSyncJobService.callJobFinished(syncOperation.jobId, false);
                         runSyncFinishedOrCanceledH(null, asc);
                     }
-                    removeSyncOperationFromCache(op.jobId);
                     getJobScheduler().cancel(op.jobId);
                 }
             }
@@ -2713,7 +2680,7 @@
 
         private void removePeriodicSyncH(EndPoint target, Bundle extras) {
             verifyJobScheduler();
-            List<SyncOperation> ops = getAllPendingSyncsFromCache();
+            List<SyncOperation> ops = getAllPendingSyncs();
             for (SyncOperation op: ops) {
                 if (op.isPeriodic && op.target.matchesSpec(target)
                         && syncExtrasEquals(op.extras, extras, true /* includeSyncSettings */)) {
@@ -2889,7 +2856,7 @@
         private void reschedulePeriodicSyncH(SyncOperation syncOperation) {
             // Ensure that the periodic sync wasn't removed.
             SyncOperation periodicSync = null;
-            List<SyncOperation> ops = getAllPendingSyncsFromCache();
+            List<SyncOperation> ops = getAllPendingSyncs();
             for (SyncOperation op: ops) {
                 if (op.isPeriodic && syncOperation.matchesPeriodicOperation(op)) {
                     periodicSync = op;
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 088d96e..4527f1f 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -381,8 +381,8 @@
                             | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
                 }
 
+                final Resources res = getContext().getResources();
                 if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
-                    final Resources res = getContext().getResources();
                     mInfo.name = res.getString(
                             com.android.internal.R.string.display_manager_built_in_display_name);
                     mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
@@ -416,6 +416,11 @@
                     if (SystemProperties.getBoolean("persist.demo.hdmirotates", false)) {
                         mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
                     }
+
+                    if (!res.getBoolean(
+                                com.android.internal.R.bool.config_localDisplaysMirrorContent)) {
+                        mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
+                    }
                 }
             }
             return mInfo;
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index 8c12060..603402e 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -218,6 +218,9 @@
     //            True by default.
     static final String PROPERTY_WAKE_ON_HOTPLUG = "ro.hdmi.wake_on_hotplug";
 
+    // TODO(OEM): Set this to true to enable 'Set Menu Language' feature. False by default.
+    static final String PROPERTY_SET_MENU_LANGUAGE = "ro.hdmi.set_menu_language";
+
     // Set to false to allow playback device to go to suspend mode even
     // when it's an active source. True by default.
     static final String PROPERTY_KEEP_AWAKE = "persist.sys.hdmi.keep_awake";
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 39c6732..a36e671 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -46,6 +46,9 @@
     private static final boolean WAKE_ON_HOTPLUG =
             SystemProperties.getBoolean(Constants.PROPERTY_WAKE_ON_HOTPLUG, true);
 
+    private static final boolean SET_MENU_LANGUAGE =
+            SystemProperties.getBoolean(Constants.PROPERTY_SET_MENU_LANGUAGE, false);
+
     private boolean mIsActiveSource = false;
 
     // Used to keep the device awake while it is the active source. For devices that
@@ -316,6 +319,9 @@
     @ServiceThreadOnly
     protected boolean handleSetMenuLanguage(HdmiCecMessage message) {
         assertRunOnServiceThread();
+        if (!SET_MENU_LANGUAGE) {
+            return false;
+        }
 
         try {
             String iso3Language = new String(message.getParams(), 0, 3, "US-ASCII");
@@ -345,6 +351,7 @@
             Slog.w(TAG, "Can't handle <Set Menu Language> of " + iso3Language);
             return false;
         } catch (UnsupportedEncodingException e) {
+            Slog.w(TAG, "Can't handle <Set Menu Language>", e);
             return false;
         }
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 459c47f..fed7e4b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -419,6 +419,7 @@
             IntentFilter filter = new IntentFilter();
             filter.addAction(Intent.ACTION_SCREEN_OFF);
             filter.addAction(Intent.ACTION_SCREEN_ON);
+            filter.addAction(Intent.ACTION_SHUTDOWN);
             filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
             getContext().registerReceiver(mHdmiControlBroadcastReceiver, filter);
 
diff --git a/services/core/java/com/android/server/job/JobSchedulerInternal.java b/services/core/java/com/android/server/job/JobSchedulerInternal.java
new file mode 100644
index 0000000..75170ec
--- /dev/null
+++ b/services/core/java/com/android/server/job/JobSchedulerInternal.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job;
+
+import android.app.job.JobInfo;
+
+import java.util.List;
+
+/**
+ * JobScheduler local system service interface.
+ * {@hide} Only for use within the system server.
+ */
+public interface JobSchedulerInternal {
+
+    /**
+     * Returns a list of pending jobs scheduled by the system service.
+     */
+    List<JobInfo> getSystemScheduledPendingJobs();
+}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index d2b77aa..cee46195 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -45,6 +45,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Process;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -505,6 +506,7 @@
 
     @Override
     public void onStart() {
+        publishLocalService(JobSchedulerInternal.class, new LocalService());
         publishBinderService(Context.JOB_SCHEDULER_SERVICE, mJobSchedulerStub);
     }
 
@@ -1178,6 +1180,28 @@
         return -1;
     }
 
+    final class LocalService implements JobSchedulerInternal {
+
+        /**
+         * Returns a list of all pending jobs. A running job is not considered pending. Periodic
+         * jobs are always considered pending.
+         */
+        public List<JobInfo> getSystemScheduledPendingJobs() {
+            synchronized (mLock) {
+                final List<JobInfo> pendingJobs = new ArrayList<JobInfo>();
+                mJobs.forEachJob(Process.SYSTEM_UID, new JobStatusFunctor() {
+                    @Override
+                    public void process(JobStatus job) {
+                        if (job.getJob().isPeriodic() || !isCurrentlyActiveLocked(job)) {
+                            pendingJobs.add(job.getJob());
+                        }
+                    }
+                });
+                return pendingJobs;
+            }
+        }
+    }
+
     /**
      * Binder stub trampoline implementation
      */
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 9837a56..55f37b8 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -210,6 +210,10 @@
         mJobSet.forEachJob(functor);
     }
 
+    public void forEachJob(int uid, JobStatusFunctor functor) {
+        mJobSet.forEachJob(uid, functor);
+    }
+
     public interface JobStatusFunctor {
         public void process(JobStatus jobStatus);
     }
@@ -870,5 +874,14 @@
                 }
             }
         }
+
+        public void forEachJob(int uid, JobStatusFunctor functor) {
+            ArraySet<JobStatus> jobs = mJobs.get(uid);
+            if (jobs != null) {
+                for (int i = jobs.size() - 1; i >= 0; i--) {
+                    functor.process(jobs.valueAt(i));
+                }
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index bd06645..6ef425a 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -185,7 +185,7 @@
         pw.println("Conn.");
         pw.println("connected: " + mNetworkConnected + " unmetered: " + mNetworkUnmetered);
         for (JobStatus js: mTrackedJobs) {
-            pw.println(String.valueOf(js.hashCode()).substring(0, 3) + ".."
+            pw.println(String.valueOf(js.getJobId() + "," + js.getUid())
                     + ": C=" + js.hasConnectivityConstraint()
                     + ", UM=" + js.hasUnmeteredConstraint());
         }
diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java
index 7638494..d9eb45c 100644
--- a/services/core/java/com/android/server/job/controllers/IdleController.java
+++ b/services/core/java/com/android/server/job/controllers/IdleController.java
@@ -197,7 +197,7 @@
         for (int i = 0; i < mTrackedTasks.size(); i++) {
             final JobStatus js = mTrackedTasks.get(i);
             pw.print("  ");
-            pw.print(String.valueOf(js.hashCode()).substring(0, 3));
+            pw.print(String.valueOf(js.getJobId() + "," + js.getUid()));
             pw.println("..");
         }
     }
diff --git a/services/core/java/com/android/server/job/controllers/TimeController.java b/services/core/java/com/android/server/job/controllers/TimeController.java
index 620800c..36fa9ec 100644
--- a/services/core/java/com/android/server/job/controllers/TimeController.java
+++ b/services/core/java/com/android/server/job/controllers/TimeController.java
@@ -145,6 +145,9 @@
                 final long jobDeadline = job.getLatestRunTimeElapsed();
 
                 if (jobDeadline <= nowElapsedMillis) {
+                    if (job.hasTimingDelayConstraint()) {
+                        job.setTimingDelayConstraintSatisfied(true);
+                    }
                     job.setDeadlineConstraintSatisfied(true);
                     mStateChangedListener.onRunJobNow(job);
                     it.remove();
@@ -281,7 +284,7 @@
                 + "s");
         pw.println("Tracking:");
         for (JobStatus ts : mTrackedJobs) {
-            pw.println(String.valueOf(ts.hashCode()).substring(0, 3) + ".."
+            pw.println(String.valueOf(ts.getJobId() + "," + ts.getUid())
                     + ": (" + (ts.hasTimingDelayConstraint() ? ts.getEarliestRunTime() : "N/A")
                     + ", " + (ts.hasDeadlineConstraint() ?ts.getLatestRunTimeElapsed() : "N/A")
                     + ")");
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
index a626b5b..9cfb590 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
@@ -24,6 +24,7 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -364,9 +365,12 @@
     private List<NetworkPolicy> getWifiPolicies() throws RemoteException {
         // First gets a list of saved wi-fi networks.
         final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
-        final Set<String> ssids = new HashSet<>(configs.size());
-        for (WifiConfiguration config : configs) {
-            ssids.add(removeDoubleQuotes(config.SSID));
+        final int size = configs != null ? configs.size() : 0;
+        final Set<String> ssids = new HashSet<>(size);
+        if (configs != null) {
+            for (WifiConfiguration config : configs) {
+                ssids.add(removeDoubleQuotes(config.SSID));
+            }
         }
 
         // Then gets the saved policies.
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index d986e94b..673dd8f 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -17,8 +17,8 @@
 package com.android.server.net;
 
 import static android.net.NetworkStats.IFACE_ALL;
-import static android.net.NetworkStats.ROAMING_DEFAULT;
-import static android.net.NetworkStats.ROAMING_ROAMING;
+import static android.net.NetworkStats.ROAMING_NO;
+import static android.net.NetworkStats.ROAMING_YES;
 import static android.net.NetworkStats.SET_ALL;
 import static android.net.NetworkStats.SET_DEFAULT;
 import static android.net.NetworkStats.TAG_NONE;
@@ -242,7 +242,7 @@
                 entry.uid = key.uid;
                 entry.set = key.set;
                 entry.tag = key.tag;
-                entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_ROAMING : ROAMING_DEFAULT;
+                entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_YES : ROAMING_NO;
                 entry.rxBytes = historyEntry.rxBytes;
                 entry.rxPackets = historyEntry.rxPackets;
                 entry.txBytes = historyEntry.txBytes;
diff --git a/services/core/java/com/android/server/notification/EventConditionProvider.java b/services/core/java/com/android/server/notification/EventConditionProvider.java
index ab3cb83..5bc9b1c 100644
--- a/services/core/java/com/android/server/notification/EventConditionProvider.java
+++ b/services/core/java/com/android/server/notification/EventConditionProvider.java
@@ -26,7 +26,9 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.service.notification.Condition;
@@ -42,6 +44,8 @@
 import com.android.server.notification.NotificationManagerService.DumpFilter;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Built-in zen condition provider for calendar event-based conditions.
@@ -63,15 +67,18 @@
     private final ArraySet<Uri> mSubscriptions = new ArraySet<Uri>();
     private final SparseArray<CalendarTracker> mTrackers = new SparseArray<>();
     private final Handler mWorker;
+    private final HandlerThread mThread;
 
     private boolean mConnected;
     private boolean mRegistered;
     private boolean mBootComplete;  // don't hammer the calendar provider until boot completes.
     private long mNextAlarmTime;
 
-    public EventConditionProvider(Looper worker) {
+    public EventConditionProvider() {
         if (DEBUG) Slog.d(TAG, "new " + SIMPLE_NAME + "()");
-        mWorker = new Handler(worker);
+        mThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
+        mThread.start();
+        mWorker = new Handler(mThread.getLooper());
     }
 
     @Override
@@ -91,10 +98,12 @@
         pw.print("      mRegistered="); pw.println(mRegistered);
         pw.print("      mBootComplete="); pw.println(mBootComplete);
         dumpUpcomingTime(pw, "mNextAlarmTime", mNextAlarmTime, System.currentTimeMillis());
-        pw.println("      mSubscriptions=");
-        for (Uri conditionId : mSubscriptions) {
-            pw.print("        ");
-            pw.println(conditionId);
+        synchronized (mSubscriptions) {
+            pw.println("      mSubscriptions=");
+            for (Uri conditionId : mSubscriptions) {
+                pw.print("        ");
+                pw.println(conditionId);
+            }
         }
         pw.println("      mTrackers=");
         for (int i = 0; i < mTrackers.size(); i++) {
@@ -137,19 +146,23 @@
     public void onSubscribe(Uri conditionId) {
         if (DEBUG) Slog.d(TAG, "onSubscribe " + conditionId);
         if (!ZenModeConfig.isValidEventConditionId(conditionId)) {
-            notifyCondition(conditionId, Condition.STATE_FALSE, "badCondition");
+            notifyCondition(createCondition(conditionId, Condition.STATE_FALSE));
             return;
         }
-        if (mSubscriptions.add(conditionId)) {
-            evaluateSubscriptions();
+        synchronized (mSubscriptions) {
+            if (mSubscriptions.add(conditionId)) {
+                evaluateSubscriptions();
+            }
         }
     }
 
     @Override
     public void onUnsubscribe(Uri conditionId) {
         if (DEBUG) Slog.d(TAG, "onUnsubscribe " + conditionId);
-        if (mSubscriptions.remove(conditionId)) {
-            evaluateSubscriptions();
+        synchronized (mSubscriptions) {
+            if (mSubscriptions.remove(conditionId)) {
+                evaluateSubscriptions();
+            }
         }
     }
 
@@ -193,51 +206,61 @@
             return;
         }
         final long now = System.currentTimeMillis();
-        for (int i = 0; i < mTrackers.size(); i++) {
-            mTrackers.valueAt(i).setCallback(mSubscriptions.isEmpty() ? null : mTrackerCallback);
-        }
-        setRegistered(!mSubscriptions.isEmpty());
-        long reevaluateAt = 0;
-        for (Uri conditionId : mSubscriptions) {
-            final EventInfo event = ZenModeConfig.tryParseEventConditionId(conditionId);
-            if (event == null) {
-                notifyCondition(conditionId, Condition.STATE_FALSE, "badConditionId");
-                continue;
+        List<Condition> conditionsToNotify = new ArrayList<>();
+        synchronized (mSubscriptions) {
+            for (int i = 0; i < mTrackers.size(); i++) {
+                mTrackers.valueAt(i).setCallback(
+                        mSubscriptions.isEmpty() ? null : mTrackerCallback);
             }
-            CheckEventResult result = null;
-            if (event.calendar == null) { // any calendar
-                // event could exist on any tracker
-                for (int i = 0; i < mTrackers.size(); i++) {
-                    final CalendarTracker tracker = mTrackers.valueAt(i);
-                    final CheckEventResult r = tracker.checkEvent(event, now);
-                    if (result == null) {
-                        result = r;
-                    } else {
-                        result.inEvent |= r.inEvent;
-                        result.recheckAt = Math.min(result.recheckAt, r.recheckAt);
-                    }
-                }
-            } else {
-                // event should exist on one tracker
-                final int userId = EventInfo.resolveUserId(event.userId);
-                final CalendarTracker tracker = mTrackers.get(userId);
-                if (tracker == null) {
-                    Slog.w(TAG, "No calendar tracker found for user " + userId);
-                    notifyCondition(conditionId, Condition.STATE_FALSE, "badUserId");
+            setRegistered(!mSubscriptions.isEmpty());
+            long reevaluateAt = 0;
+            for (Uri conditionId : mSubscriptions) {
+                final EventInfo event = ZenModeConfig.tryParseEventConditionId(conditionId);
+                if (event == null) {
+                    conditionsToNotify.add(createCondition(conditionId, Condition.STATE_FALSE));
                     continue;
                 }
-                result = tracker.checkEvent(event, now);
+                CheckEventResult result = null;
+                if (event.calendar == null) { // any calendar
+                    // event could exist on any tracker
+                    for (int i = 0; i < mTrackers.size(); i++) {
+                        final CalendarTracker tracker = mTrackers.valueAt(i);
+                        final CheckEventResult r = tracker.checkEvent(event, now);
+                        if (result == null) {
+                            result = r;
+                        } else {
+                            result.inEvent |= r.inEvent;
+                            result.recheckAt = Math.min(result.recheckAt, r.recheckAt);
+                        }
+                    }
+                } else {
+                    // event should exist on one tracker
+                    final int userId = EventInfo.resolveUserId(event.userId);
+                    final CalendarTracker tracker = mTrackers.get(userId);
+                    if (tracker == null) {
+                        Slog.w(TAG, "No calendar tracker found for user " + userId);
+                        conditionsToNotify.add(createCondition(conditionId, Condition.STATE_FALSE));
+                        continue;
+                    }
+                    result = tracker.checkEvent(event, now);
+                }
+                if (result.recheckAt != 0
+                        && (reevaluateAt == 0 || result.recheckAt < reevaluateAt)) {
+                    reevaluateAt = result.recheckAt;
+                }
+                if (!result.inEvent) {
+                    conditionsToNotify.add(createCondition(conditionId, Condition.STATE_FALSE));
+                    continue;
+                }
+                conditionsToNotify.add(createCondition(conditionId, Condition.STATE_TRUE));
             }
-            if (result.recheckAt != 0 && (reevaluateAt == 0 || result.recheckAt < reevaluateAt)) {
-                reevaluateAt = result.recheckAt;
-            }
-            if (!result.inEvent) {
-                notifyCondition(conditionId, Condition.STATE_FALSE, "!inEventNow");
-                continue;
-            }
-            notifyCondition(conditionId, Condition.STATE_TRUE, "inEventNow");
+            rescheduleAlarm(now, reevaluateAt);
         }
-        rescheduleAlarm(now, reevaluateAt);
+        for (Condition condition : conditionsToNotify) {
+            if (condition != null) {
+                notifyCondition(condition);
+            }
+        }
         if (DEBUG) Slog.d(TAG, "evaluateSubscriptions took " + (System.currentTimeMillis() - now));
     }
 
@@ -261,12 +284,6 @@
         alarms.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent);
     }
 
-    private void notifyCondition(Uri conditionId, int state, String reason) {
-        if (DEBUG) Slog.d(TAG, "notifyCondition " + conditionId + " "
-                + Condition.stateToString(state) + " reason=" + reason);
-        notifyCondition(createCondition(conditionId, state));
-    }
-
     private Condition createCondition(Uri id, int state) {
         final String summary = NOT_SHOWN;
         final String line1 = NOT_SHOWN;
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 6cf3940..6d9fed4 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -238,7 +238,7 @@
                 rebuildRestoredPackages();
             }
             // make sure we're still bound to any of our services who may have just upgraded
-            rebindServices();
+            rebindServices(false);
         }
     }
 
@@ -249,13 +249,13 @@
             if (DEBUG) Slog.d(TAG, "Current profile IDs didn't change, skipping rebindServices().");
             return;
         }
-        rebindServices();
+        rebindServices(true);
     }
 
     public void onUserUnlocked(int user) {
         if (DEBUG) Slog.d(TAG, "onUserUnlocked u=" + user);
         rebuildRestoredPackages();
-        rebindServices();
+        rebindServices(false);
     }
 
     public ManagedServiceInfo getServiceFromTokenLocked(IInterface service) {
@@ -543,7 +543,7 @@
      * Called whenever packages change, the user switches, or the secure setting
      * is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
      */
-    private void rebindServices() {
+    private void rebindServices(boolean forceRebind) {
         if (DEBUG) Slog.d(TAG, "rebindServices");
         final int[] userIds = mUserProfiles.getCurrentProfileIds();
         final int nUserIds = userIds.length;
@@ -559,15 +559,15 @@
         final SparseArray<Set<ComponentName>> toAdd = new SparseArray<>();
 
         synchronized (mMutex) {
-            // Potentially unbind automatically bound services, retain system services.
+            // Rebind to non-system services if user switched
             for (ManagedServiceInfo service : mServices) {
                 if (!service.isSystem && !service.isGuest(this)) {
                     removableBoundServices.add(service);
                 }
             }
 
-            final ArraySet<ComponentName> newEnabled = new ArraySet<>();
-            final ArraySet<String> newPackages = new ArraySet<>();
+            mEnabledServicesForCurrentProfiles.clear();
+            mEnabledServicesPackageNames.clear();
 
             for (int i = 0; i < nUserIds; ++i) {
                 // decode the list of components
@@ -591,15 +591,13 @@
 
                 toAdd.put(userIds[i], add);
 
-                newEnabled.addAll(userComponents);
+                mEnabledServicesForCurrentProfiles.addAll(userComponents);
 
                 for (int j = 0; j < userComponents.size(); j++) {
                     final ComponentName component = userComponents.valueAt(j);
-                    newPackages.add(component.getPackageName());
+                    mEnabledServicesPackageNames.add(component.getPackageName());
                 }
             }
-            mEnabledServicesForCurrentProfiles = newEnabled;
-            mEnabledServicesPackageNames = newPackages;
         }
 
         for (ManagedServiceInfo info : removableBoundServices) {
@@ -607,11 +605,11 @@
             final int oldUser = info.userid;
             final Set<ComponentName> allowedComponents = toAdd.get(info.userid);
             if (allowedComponents != null) {
-                if (allowedComponents.contains(component)) {
+                if (allowedComponents.contains(component) && !forceRebind) {
                     // Already bound, don't need to bind again.
                     allowedComponents.remove(component);
                 } else {
-                    // No longer allowed to be bound.
+                    // No longer allowed to be bound, or must rebind.
                     Slog.v(TAG, "disabling " + getCaption() + " for user "
                             + oldUser + ": " + component);
                     unregisterService(component, oldUser);
@@ -622,8 +620,7 @@
         for (int i = 0; i < nUserIds; ++i) {
             final Set<ComponentName> add = toAdd.get(userIds[i]);
             for (ComponentName component : add) {
-                Slog.v(TAG, "enabling " + getCaption() + " for user " + userIds[i] + ": "
-                        + component);
+                Slog.v(TAG, "enabling " + getCaption() + " for " + userIds[i] + ": " + component);
                 registerService(component, userIds[i]);
             }
         }
@@ -859,7 +856,7 @@
             if (uri == null || mSecureSettingsUri.equals(uri)) {
                 if (DEBUG) Slog.d(TAG, "Setting changed: mSecureSettingsUri=" + mSecureSettingsUri +
                         " / uri=" + uri);
-                rebindServices();
+                rebindServices(false);
                 rebuildRestoredPackages();
             }
         }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 02c786e..e8a6528 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -43,6 +43,7 @@
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
 import android.Manifest;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
@@ -155,9 +156,11 @@
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
@@ -218,7 +221,7 @@
     private IActivityManager mAm;
     AudioManager mAudioManager;
     AudioManagerInternal mAudioManagerInternal;
-    StatusBarManagerInternal mStatusBar;
+    @Nullable StatusBarManagerInternal mStatusBar;
     Vibrator mVibrator;
     private VrManagerInternal mVrManagerInternal;
 
@@ -274,9 +277,6 @@
     // Persistent storage for notification policy
     private AtomicFile mPolicyFile;
 
-    // Temporary holder for <blocked-packages> config coming from old policy files.
-    private HashSet<String> mBlockedPackages = new HashSet<String>();
-
     private static final int DB_VERSION = 1;
 
     private static final String TAG_NOTIFICATION_POLICY = "notification-policy";
@@ -352,27 +352,7 @@
         final XmlPullParser parser = Xml.newPullParser();
         parser.setInput(stream, StandardCharsets.UTF_8.name());
 
-        int type;
-        String tag;
-        int version = DB_VERSION;
-        while ((type = parser.next()) != END_DOCUMENT) {
-            tag = parser.getName();
-            if (type == START_TAG) {
-                if (TAG_NOTIFICATION_POLICY.equals(tag)) {
-                    version = Integer.parseInt(
-                            parser.getAttributeValue(null, ATTR_VERSION));
-                } else if (TAG_BLOCKED_PKGS.equals(tag)) {
-                    while ((type = parser.next()) != END_DOCUMENT) {
-                        tag = parser.getName();
-                        if (TAG_PACKAGE.equals(tag)) {
-                            mBlockedPackages.add(
-                                    parser.getAttributeValue(null, ATTR_NAME));
-                        } else if (TAG_BLOCKED_PKGS.equals(tag) && type == END_TAG) {
-                            break;
-                        }
-                    }
-                }
-            }
+        while (parser.next() != END_DOCUMENT) {
             mZenModeHelper.readXml(parser, forRestore);
             mRankingHelper.readXml(parser, forRestore);
         }
@@ -381,7 +361,6 @@
     private void loadPolicyFile() {
         if (DBG) Slog.d(TAG, "loadPolicyFile");
         synchronized(mPolicyFile) {
-            mBlockedPackages.clear();
 
             FileInputStream infile = null;
             try {
@@ -795,7 +774,9 @@
             } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
                 // turn off LED when user passes through lock screen
                 mNotificationLight.turnOff();
-                mStatusBar.notificationLightOff();
+                if (mStatusBar != null) {
+                    mStatusBar.notificationLightOff();
+                }
             } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
                 final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
                 // reload per-user settings
@@ -859,7 +840,9 @@
     private final Runnable mBuzzBeepBlinked = new Runnable() {
         @Override
         public void run() {
-            mStatusBar.buzzBeepBlinked();
+            if (mStatusBar != null) {
+                mStatusBar.buzzBeepBlinked();
+            }
         }
     };
 
@@ -935,7 +918,7 @@
         final File systemDir = new File(Environment.getDataDirectory(), "system");
         mPolicyFile = new AtomicFile(new File(systemDir, "notification_policy.xml"));
 
-        importOldBlockDb();
+        syncBlockDb();
 
         // This is a MangedServices object that keeps track of the listeners.
         mListeners = new NotificationListeners();
@@ -943,22 +926,12 @@
         // This is a MangedServices object that keeps track of the ranker.
         mRankerServices = new NotificationRankers();
         // Find the updatable ranker and register it.
-        Set<ComponentName> rankerComponents = mRankerServices.queryPackageForServices(
-                mRankerServicePackageName, UserHandle.USER_SYSTEM, null);
-        Iterator<ComponentName> iterator = rankerComponents.iterator();
-        if (iterator.hasNext()) {
-            ComponentName rankerComponent = iterator.next();
-            if (iterator.hasNext()) {
-                Slog.e(TAG, "found multiple ranker services:" + rankerComponents);
-            } else {
-                mRankerServices.registerSystemService(rankerComponent, UserHandle.USER_SYSTEM);
-            }
-        } else {
-            Slog.w(TAG, "could not start ranker service: none found");
-        }
+        mRankerServices.registerRanker();
 
         mStatusBar = getLocalService(StatusBarManagerInternal.class);
-        mStatusBar.setNotificationDelegate(mNotificationDelegate);
+        if (mStatusBar != null) {
+            mStatusBar.setNotificationDelegate(mNotificationDelegate);
+        }
 
         final LightsManager lights = getLocalService(LightsManager.class);
         mNotificationLight = lights.getLight(LightsManager.LIGHT_ID_NOTIFICATIONS);
@@ -1045,22 +1018,43 @@
     }
 
     /**
-     * Read the old XML-based app block database and import those blockages into the AppOps system.
+     * Make sure the XML config and the the AppOps system agree about blocks.
      */
-    private void importOldBlockDb() {
+    private void syncBlockDb() {
         loadPolicyFile();
 
-        PackageManager pm = getContext().getPackageManager();
-        for (String pkg : mBlockedPackages) {
-            PackageInfo info = null;
-            try {
-                info = pm.getPackageInfo(pkg, 0);
-                setNotificationsEnabledForPackageImpl(pkg, info.applicationInfo.uid, false);
-            } catch (NameNotFoundException e) {
-                // forget you
+        // sync bans from ranker into app opps
+        Map<Integer, String> packageBans = mRankingHelper.getPackageBans();
+        for(Entry<Integer, String> ban : packageBans.entrySet()) {
+            final int uid = ban.getKey();
+            final String packageName = ban.getValue();
+            setNotificationsEnabledForPackageImpl(packageName, uid, false);
+        }
+
+        // sync bans from app opps into ranker
+        packageBans.clear();
+        for (UserInfo user : UserManager.get(getContext()).getUsers()) {
+            final int userId = user.getUserHandle().getIdentifier();
+            final PackageManager packageManager = getContext().getPackageManager();
+            List<PackageInfo> packages = packageManager.getInstalledPackagesAsUser(0, userId);
+            final int packageCount = packages.size();
+            for (int p = 0; p < packageCount; p++) {
+                final String packageName = packages.get(p).packageName;
+                try {
+                    final int uid = packageManager.getPackageUidAsUser(packageName, userId);
+                    if (!checkNotificationOp(packageName, uid)) {
+                        packageBans.put(uid, packageName);
+                    }
+                } catch (NameNotFoundException e) {
+                    // forget you
+                }
             }
         }
-        mBlockedPackages.clear();
+        for (Entry<Integer, String> ban : packageBans.entrySet()) {
+            mRankingHelper.setImportance(ban.getValue(), ban.getKey(), IMPORTANCE_NONE);
+        }
+
+        savePolicyFile();
     }
 
     @Override
@@ -1265,6 +1259,8 @@
             checkCallerIsSystem();
 
             setNotificationsEnabledForPackageImpl(pkg, uid, enabled);
+            mRankingHelper.setEnabled(pkg, uid, enabled);
+            savePolicyFile();
         }
 
         /**
@@ -1444,16 +1440,7 @@
          */
         @Override
         public void unregisterListener(INotificationListener token, int userid) {
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                if(mRankerServices.checkServiceTokenLocked(token) != null) {
-                    mRankerServices.unregisterService(token, userid);
-                } else {
-                    mListeners.unregisterService(token, userid);
-                }
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
+            mListeners.unregisterService(token, userid);
         }
 
         /**
@@ -1820,6 +1807,16 @@
                     message);
         }
 
+        private void enforceSystemOrSystemUIOrSamePackage(String pkg, String message) {
+            try {
+                checkCallerIsSystemOrSameApp(pkg);
+            } catch (SecurityException e) {
+                getContext().enforceCallingPermission(
+                        android.Manifest.permission.STATUS_BAR_SERVICE,
+                        message);
+            }
+        }
+
         private void enforcePolicyAccess(int uid, String method) {
             if (PackageManager.PERMISSION_GRANTED == getContext().checkCallingPermission(
                     android.Manifest.permission.MANAGE_NOTIFICATIONS)) {
@@ -1946,8 +1943,9 @@
         }
 
         @Override
-        public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {
-            enforceSystemOrSystemUI("request policy access status for another package");
+        public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {;
+            enforceSystemOrSystemUIOrSamePackage(pkg,
+                    "request policy access status for another package");
             return checkPackagePolicyAccess(pkg);
         }
 
@@ -2036,21 +2034,8 @@
         JSONObject dump = new JSONObject();
         try {
             dump.put("service", "Notification Manager");
-            JSONArray bans = new JSONArray();
-            try {
-                ArrayMap<Integer, ArrayList<String>> packageBans = getPackageBans(filter);
-                for (Integer userId : packageBans.keySet()) {
-                    for (String packageName : packageBans.get(userId)) {
-                        JSONObject ban = new JSONObject();
-                        ban.put("userId", userId);
-                        ban.put("packageName", packageName);
-                        bans.put(ban);
-                    }
-                }
-            } catch (NameNotFoundException e) {
-                // pass
-            }
-            dump.put("bans", bans);
+            dump.put("bans", mRankingHelper.dumpBansJson(filter));
+            dump.put("ranking", mRankingHelper.dumpJson(filter));
             dump.put("stats", mUsageStats.dumpJson(filter));
         } catch (JSONException e) {
             e.printStackTrace();
@@ -2177,47 +2162,9 @@
                     r.dump(pw, "      ", getContext(), filter.redact);
                 }
             }
-
-            try {
-                pw.println("\n  Banned Packages:");
-                ArrayMap<Integer, ArrayList<String>> packageBans = getPackageBans(filter);
-                for (Integer userId : packageBans.keySet()) {
-                    for (String packageName : packageBans.get(userId)) {
-                        pw.println("    " + userId + ": " + packageName);
-                    }
-                }
-            } catch (NameNotFoundException e) {
-                // pass
-            }
         }
     }
 
-    private ArrayMap<Integer, ArrayList<String>> getPackageBans(DumpFilter filter)
-            throws NameNotFoundException {
-        ArrayMap<Integer, ArrayList<String>> packageBans = new ArrayMap<>();
-        ArrayList<String> packageNames = new ArrayList<>();
-        for (UserInfo user : UserManager.get(getContext()).getUsers()) {
-            final int userId = user.getUserHandle().getIdentifier();
-            final PackageManager packageManager = getContext().getPackageManager();
-            List<PackageInfo> packages = packageManager.getInstalledPackagesAsUser(0, userId);
-            final int packageCount = packages.size();
-            for (int p = 0; p < packageCount; p++) {
-                final String packageName = packages.get(p).packageName;
-                if (filter == null || filter.matches(packageName)) {
-                    final int uid = packageManager.getPackageUidAsUser(packageName, userId);
-                    if (!checkNotificationOp(packageName, uid)) {
-                        packageNames.add(packageName);
-                    }
-                }
-            }
-            if (!packageNames.isEmpty()) {
-                packageBans.put(userId, packageNames);
-                packageNames = new ArrayList<>();
-            }
-        }
-        return packageBans;
-    }
-
     /**
      * The private API only accessible to the system process.
      */
@@ -2300,6 +2247,11 @@
         // Sanitize inputs
         notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN,
                 Notification.PRIORITY_MAX);
+        if (notification.extras != null) {
+            // If the remote side sent us bad parcelables, they won't get the
+            // results they want, which is their loss.
+            notification.extras.setDefusable(true);
+        }
 
         // setup local book-keeping
         final StatusBarNotification n = new StatusBarNotification(
@@ -3310,7 +3262,9 @@
         // Don't flash while we are in a call or screen is on
         if (ledNotification == null || mInCall || mScreenOn) {
             mNotificationLight.turnOff();
-            mStatusBar.notificationLightOff();
+            if (mStatusBar != null) {
+                mStatusBar.notificationLightOff();
+            }
         } else {
             final Notification ledno = ledNotification.sbn.getNotification();
             int ledARGB = ledno.ledARGB;
@@ -3326,8 +3280,10 @@
                 mNotificationLight.setFlashing(ledARGB, Light.LIGHT_FLASH_TIMED,
                         ledOnMS, ledOffMS);
             }
-            // let SystemUI make an independent decision
-            mStatusBar.notificationLightPulse(ledARGB, ledOnMS, ledOffMS);
+            if (mStatusBar != null) {
+                // let SystemUI make an independent decision
+                mStatusBar.notificationLightPulse(ledARGB, ledOnMS, ledOffMS);
+            }
         }
     }
 
@@ -3583,6 +3539,45 @@
         public boolean isEnabled() {
             return !mServices.isEmpty();
         }
+
+        @Override
+        public void onUserSwitched(int user) {
+            for (ManagedServiceInfo info : mServices) {
+                unregisterService(info.service, info.userid);
+            }
+            registerRanker();
+        }
+
+        @Override
+        public void onPackagesChanged(boolean queryReplace, String[] pkgList) {
+            if (DEBUG) Slog.d(TAG, "onPackagesChanged queryReplace=" + queryReplace
+                    + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList)));
+
+            if (pkgList != null && (pkgList.length > 0)) {
+                for (String pkgName : pkgList) {
+                    if (mRankerServicePackageName.equals(pkgName)) {
+                        registerRanker();
+                    }
+                }
+            }
+        }
+
+        protected void registerRanker() {
+            // Find the updatable ranker and register it.
+            Set<ComponentName> rankerComponents = queryPackageForServices(
+                    mRankerServicePackageName, UserHandle.USER_SYSTEM, null);
+            Iterator<ComponentName> iterator = rankerComponents.iterator();
+            if (iterator.hasNext()) {
+                ComponentName rankerComponent = iterator.next();
+                if (iterator.hasNext()) {
+                    Slog.e(TAG, "found multiple ranker services:" + rankerComponents);
+                } else {
+                    registerSystemService(rankerComponent, UserHandle.USER_SYSTEM);
+                }
+            } else {
+                Slog.w(TAG, "could not start ranker service: none found");
+            }
+        }
     }
 
     public class NotificationListeners extends ManagedServices {
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index 538f951..b853417 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -336,6 +336,13 @@
             finalImportance = new ImportanceHistogram(context, "note_importance_");
         }
 
+        public AggregatedStats getPrevious() {
+            if (mPrevious == null) {
+                mPrevious = new AggregatedStats(mContext, key);
+            }
+            return mPrevious;
+        }
+
         public void countApiUse(NotificationRecord record) {
             final Notification n = record.getNotification();
             if (n.actions != null) {
@@ -411,67 +418,64 @@
         }
 
         public void emit() {
-            if (mPrevious == null) {
-                mPrevious = new AggregatedStats(null, key);
-            }
+            AggregatedStats previous = getPrevious();
+            maybeCount("note_post", (numPostedByApp - previous.numPostedByApp));
+            maybeCount("note_update", (numUpdatedByApp - previous.numUpdatedByApp));
+            maybeCount("note_remove", (numRemovedByApp - previous.numRemovedByApp));
+            maybeCount("note_with_people", (numWithValidPeople - previous.numWithValidPeople));
+            maybeCount("note_with_stars", (numWithStaredPeople - previous.numWithStaredPeople));
+            maybeCount("people_cache_hit", (numPeopleCacheHit - previous.numPeopleCacheHit));
+            maybeCount("people_cache_miss", (numPeopleCacheMiss - previous.numPeopleCacheMiss));
+            maybeCount("note_blocked", (numBlocked - previous.numBlocked));
+            maybeCount("note_suspended", (numSuspendedByAdmin - previous.numSuspendedByAdmin));
+            maybeCount("note_with_actions", (numWithActions - previous.numWithActions));
+            maybeCount("note_private", (numPrivate - previous.numPrivate));
+            maybeCount("note_secret", (numSecret - previous.numSecret));
+            maybeCount("note_interupt", (numInterrupt - previous.numInterrupt));
+            maybeCount("note_big_text", (numWithBigText - previous.numWithBigText));
+            maybeCount("note_big_pic", (numWithBigPicture - previous.numWithBigPicture));
+            maybeCount("note_fg", (numForegroundService - previous.numForegroundService));
+            maybeCount("note_ongoing", (numOngoing - previous.numOngoing));
+            maybeCount("note_auto", (numAutoCancel - previous.numAutoCancel));
+            maybeCount("note_large_icon", (numWithLargeIcon - previous.numWithLargeIcon));
+            maybeCount("note_inbox", (numWithInbox - previous.numWithInbox));
+            maybeCount("note_media", (numWithMediaSession - previous.numWithMediaSession));
+            maybeCount("note_title", (numWithTitle - previous.numWithTitle));
+            maybeCount("note_text", (numWithText - previous.numWithText));
+            maybeCount("note_sub_text", (numWithSubText - previous.numWithSubText));
+            maybeCount("note_info_text", (numWithInfoText - previous.numWithInfoText));
+            noisyImportance.maybeCount(previous.noisyImportance);
+            quietImportance.maybeCount(previous.quietImportance);
+            finalImportance.maybeCount(previous.finalImportance);
 
-            maybeCount("note_post", (numPostedByApp - mPrevious.numPostedByApp));
-            maybeCount("note_update", (numUpdatedByApp - mPrevious.numUpdatedByApp));
-            maybeCount("note_remove", (numRemovedByApp - mPrevious.numRemovedByApp));
-            maybeCount("note_with_people", (numWithValidPeople - mPrevious.numWithValidPeople));
-            maybeCount("note_with_stars", (numWithStaredPeople - mPrevious.numWithStaredPeople));
-            maybeCount("people_cache_hit", (numPeopleCacheHit - mPrevious.numPeopleCacheHit));
-            maybeCount("people_cache_miss", (numPeopleCacheMiss - mPrevious.numPeopleCacheMiss));
-            maybeCount("note_blocked", (numBlocked - mPrevious.numBlocked));
-            maybeCount("note_suspended", (numSuspendedByAdmin - mPrevious.numSuspendedByAdmin));
-            maybeCount("note_with_actions", (numWithActions - mPrevious.numWithActions));
-            maybeCount("note_private", (numPrivate - mPrevious.numPrivate));
-            maybeCount("note_secret", (numSecret - mPrevious.numSecret));
-            maybeCount("note_interupt", (numInterrupt - mPrevious.numInterrupt));
-            maybeCount("note_big_text", (numWithBigText - mPrevious.numWithBigText));
-            maybeCount("note_big_pic", (numWithBigPicture - mPrevious.numWithBigPicture));
-            maybeCount("note_fg", (numForegroundService - mPrevious.numForegroundService));
-            maybeCount("note_ongoing", (numOngoing - mPrevious.numOngoing));
-            maybeCount("note_auto", (numAutoCancel - mPrevious.numAutoCancel));
-            maybeCount("note_large_icon", (numWithLargeIcon - mPrevious.numWithLargeIcon));
-            maybeCount("note_inbox", (numWithInbox - mPrevious.numWithInbox));
-            maybeCount("note_media", (numWithMediaSession - mPrevious.numWithMediaSession));
-            maybeCount("note_title", (numWithTitle - mPrevious.numWithTitle));
-            maybeCount("note_text", (numWithText - mPrevious.numWithText));
-            maybeCount("note_sub_text", (numWithSubText - mPrevious.numWithSubText));
-            maybeCount("note_info_text", (numWithInfoText - mPrevious.numWithInfoText));
-            noisyImportance.maybeCount(mPrevious.noisyImportance);
-            quietImportance.maybeCount(mPrevious.quietImportance);
-            finalImportance.maybeCount(mPrevious.finalImportance);
-
-            mPrevious.numPostedByApp = numPostedByApp;
-            mPrevious.numUpdatedByApp = numUpdatedByApp;
-            mPrevious.numRemovedByApp = numRemovedByApp;
-            mPrevious.numPeopleCacheHit = numPeopleCacheHit;
-            mPrevious.numPeopleCacheMiss = numPeopleCacheMiss;
-            mPrevious.numWithStaredPeople = numWithStaredPeople;
-            mPrevious.numWithValidPeople = numWithValidPeople;
-            mPrevious.numBlocked = numBlocked;
-            mPrevious.numSuspendedByAdmin = numSuspendedByAdmin;
-            mPrevious.numWithActions = numWithActions;
-            mPrevious.numPrivate = numPrivate;
-            mPrevious.numSecret = numSecret;
-            mPrevious.numInterrupt = numInterrupt;
-            mPrevious.numWithBigText = numWithBigText;
-            mPrevious.numWithBigPicture = numWithBigPicture;
-            mPrevious.numForegroundService = numForegroundService;
-            mPrevious.numOngoing = numOngoing;
-            mPrevious.numAutoCancel = numAutoCancel;
-            mPrevious.numWithLargeIcon = numWithLargeIcon;
-            mPrevious.numWithInbox = numWithInbox;
-            mPrevious.numWithMediaSession = numWithMediaSession;
-            mPrevious.numWithTitle = numWithTitle;
-            mPrevious.numWithText = numWithText;
-            mPrevious.numWithSubText = numWithSubText;
-            mPrevious.numWithInfoText = numWithInfoText;
-            noisyImportance.update(mPrevious.noisyImportance);
-            quietImportance.update(mPrevious.quietImportance);
-            finalImportance.update(mPrevious.finalImportance);
+            previous.numPostedByApp = numPostedByApp;
+            previous.numUpdatedByApp = numUpdatedByApp;
+            previous.numRemovedByApp = numRemovedByApp;
+            previous.numPeopleCacheHit = numPeopleCacheHit;
+            previous.numPeopleCacheMiss = numPeopleCacheMiss;
+            previous.numWithStaredPeople = numWithStaredPeople;
+            previous.numWithValidPeople = numWithValidPeople;
+            previous.numBlocked = numBlocked;
+            previous.numSuspendedByAdmin = numSuspendedByAdmin;
+            previous.numWithActions = numWithActions;
+            previous.numPrivate = numPrivate;
+            previous.numSecret = numSecret;
+            previous.numInterrupt = numInterrupt;
+            previous.numWithBigText = numWithBigText;
+            previous.numWithBigPicture = numWithBigPicture;
+            previous.numForegroundService = numForegroundService;
+            previous.numOngoing = numOngoing;
+            previous.numAutoCancel = numAutoCancel;
+            previous.numWithLargeIcon = numWithLargeIcon;
+            previous.numWithInbox = numWithInbox;
+            previous.numWithMediaSession = numWithMediaSession;
+            previous.numWithTitle = numWithTitle;
+            previous.numWithText = numWithText;
+            previous.numWithSubText = numWithSubText;
+            previous.numWithInfoText = numWithInfoText;
+            noisyImportance.update(previous.noisyImportance);
+            quietImportance.update(previous.quietImportance);
+            finalImportance.update(previous.finalImportance);
         }
 
         void maybeCount(String name, int value) {
@@ -553,6 +557,7 @@
         }
 
         public JSONObject dumpJson() throws JSONException {
+            AggregatedStats previous = getPrevious();
             JSONObject dump = new JSONObject();
             dump.put("key", key);
             dump.put("duration", SystemClock.elapsedRealtime() - mCreated);
@@ -581,9 +586,9 @@
             maybePut(dump, "numWithText", numWithText);
             maybePut(dump, "numWithSubText", numWithSubText);
             maybePut(dump, "numWithInfoText", numWithInfoText);
-            noisyImportance.maybePut(dump, mPrevious.noisyImportance);
-            quietImportance.maybePut(dump, mPrevious.quietImportance);
-            finalImportance.maybePut(dump, mPrevious.finalImportance);
+            noisyImportance.maybePut(dump, previous.noisyImportance);
+            quietImportance.maybePut(dump, previous.quietImportance);
+            finalImportance.maybePut(dump, previous.finalImportance);
 
             return dump;
         }
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index fd96a78..4a41705 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -25,6 +25,11 @@
 import android.util.ArrayMap;
 import android.util.Slog;
 
+import com.android.server.notification.NotificationManagerService.DumpFilter;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -33,6 +38,8 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
 
 public class RankingHelper implements RankingConfig {
     private static final String TAG = "RankingHelper";
@@ -358,6 +365,14 @@
         updateConfig();
     }
 
+    public void setEnabled(String packageName, int uid, boolean enabled) {
+        boolean wasEnabled = getImportance(packageName, uid) != Ranking.IMPORTANCE_NONE;
+        if (wasEnabled == enabled) {
+            return;
+        }
+        setImportance(packageName, uid, enabled ? DEFAULT_IMPORTANCE : Ranking.IMPORTANCE_NONE);
+    }
+
     public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) {
         if (filter == null) {
             final int N = mSignalExtractors.length;
@@ -398,17 +413,97 @@
                 }
                 if (r.priority != DEFAULT_PRIORITY) {
                     pw.print(" priority=");
-                    pw.print(Ranking.importanceToString(r.priority));
+                    pw.print(Notification.priorityToString(r.priority));
                 }
                 if (r.visibility != DEFAULT_VISIBILITY) {
                     pw.print(" visibility=");
-                    pw.print(Ranking.importanceToString(r.visibility));
+                    pw.print(Notification.visibilityToString(r.visibility));
                 }
                 pw.println();
             }
         }
     }
 
+    public JSONObject dumpJson(NotificationManagerService.DumpFilter filter) {
+        JSONObject ranking = new JSONObject();
+        JSONArray records = new JSONArray();
+        try {
+            ranking.put("noUid", mRestoredWithoutUids.size());
+        } catch (JSONException e) {
+           // pass
+        }
+        final int N = mRecords.size();
+        for (int i = 0; i < N; i++) {
+            final Record r = mRecords.valueAt(i);
+            if (filter == null || filter.matches(r.pkg)) {
+                JSONObject record = new JSONObject();
+                try {
+                    record.put("userId", UserHandle.getUserId(r.uid));
+                    record.put("packageName", r.pkg);
+                    if (r.importance != DEFAULT_IMPORTANCE) {
+                        record.put("importance", Ranking.importanceToString(r.importance));
+                    }
+                    if (r.priority != DEFAULT_PRIORITY) {
+                        record.put("priority", Notification.priorityToString(r.priority));
+                    }
+                    if (r.visibility != DEFAULT_VISIBILITY) {
+                        record.put("visibility", Notification.visibilityToString(r.visibility));
+                    }
+                } catch (JSONException e) {
+                   // pass
+                }
+                records.put(record);
+            }
+        }
+        try {
+            ranking.put("records", records);
+        } catch (JSONException e) {
+            // pass
+        }
+        return ranking;
+    }
+
+    /**
+     * Dump only the ban information as structured JSON for the stats collector.
+     *
+     * This is intentionally redundant with {#link dumpJson} because the old
+     * scraper will expect this format.
+     *
+     * @param filter
+     * @return
+     */
+    public JSONArray dumpBansJson(NotificationManagerService.DumpFilter filter) {
+        JSONArray bans = new JSONArray();
+        Map<Integer, String> packageBans = getPackageBans();
+        for(Entry<Integer, String> ban : packageBans.entrySet()) {
+            final int userId = UserHandle.getUserId(ban.getKey());
+            final String packageName = ban.getValue();
+            if (filter == null || filter.matches(packageName)) {
+                JSONObject banJson = new JSONObject();
+                try {
+                    banJson.put("userId", userId);
+                    banJson.put("packageName", packageName);
+                } catch (JSONException e) {
+                    e.printStackTrace();
+                }
+                bans.put(banJson);
+            }
+        }
+        return bans;
+    }
+
+    public Map<Integer, String> getPackageBans() {
+        final int N = mRecords.size();
+        ArrayMap<Integer, String> packageBans = new ArrayMap<>(N);
+        for (int i = 0; i < N; i++) {
+            final Record r = mRecords.valueAt(i);
+            if (r.importance == Ranking.IMPORTANCE_NONE) {
+                packageBans.put(r.uid, r.pkg);
+            }
+        }
+        return packageBans;
+    }
+
     public void onPackagesChanged(boolean queryReplace, String[] pkgList) {
         if (queryReplace || pkgList == null || pkgList.length == 0
                 || mRestoredWithoutUids.isEmpty()) {
diff --git a/services/core/java/com/android/server/notification/ZenModeConditions.java b/services/core/java/com/android/server/notification/ZenModeConditions.java
index 9cdece5..0945065 100644
--- a/services/core/java/com/android/server/notification/ZenModeConditions.java
+++ b/services/core/java/com/android/server/notification/ZenModeConditions.java
@@ -50,7 +50,7 @@
             mConditionProviders.addSystemProvider(new ScheduleConditionProvider());
         }
         if (mConditionProviders.isSystemProviderEnabled(ZenModeConfig.EVENT_PATH)) {
-            mConditionProviders.addSystemProvider(new EventConditionProvider(helper.getLooper()));
+            mConditionProviders.addSystemProvider(new EventConditionProvider());
         }
         mConditionProviders.setCallback(this);
     }
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 5612870..5b0ceca 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -28,6 +28,7 @@
 import android.content.pm.ILauncherApps;
 import android.content.pm.IOnAppsChangedListener;
 import android.content.pm.IPackageManager;
+import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -42,6 +43,7 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IInterface;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -50,6 +52,7 @@
 import android.util.Log;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
@@ -72,9 +75,21 @@
 
     @Override
     public void onStart() {
+        Binder.LOG_RUNTIME_EXCEPTION = true;
         publishBinderService(Context.LAUNCHER_APPS_SERVICE, mLauncherAppsImpl);
     }
 
+    static class BroadcastCookie {
+        public final UserHandle user;
+        public final String packageName;
+
+        BroadcastCookie(UserHandle userHandle, String packageName) {
+            this.user = userHandle;
+            this.packageName = packageName;
+        }
+    }
+
+    @VisibleForTesting
     static class LauncherAppsImpl extends ILauncherApps.Stub {
         private static final boolean DEBUG = false;
         private static final String TAG = "LauncherAppsService";
@@ -96,12 +111,22 @@
             mShortcutServiceInternal.addListener(mPackageMonitor);
         }
 
+        @VisibleForTesting
+        int injectBinderCallingUid() {
+            return getCallingUid();
+        }
+
+        private int getCallingUserId() {
+            return UserHandle.getUserId(injectBinderCallingUid());
+        }
+
         /*
          * @see android.content.pm.ILauncherApps#addOnAppsChangedListener(
          *          android.content.pm.IOnAppsChangedListener)
          */
         @Override
-        public void addOnAppsChangedListener(IOnAppsChangedListener listener) throws RemoteException {
+        public void addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener)
+                throws RemoteException {
             synchronized (mListeners) {
                 if (DEBUG) {
                     Log.d(TAG, "Adding listener from " + Binder.getCallingUserHandle());
@@ -113,7 +138,8 @@
                     startWatchingPackageBroadcasts();
                 }
                 mListeners.unregister(listener);
-                mListeners.register(listener, Binder.getCallingUserHandle());
+                mListeners.register(listener, new BroadcastCookie(UserHandle.of(getCallingUserId()),
+                        callingPackage));
             }
         }
 
@@ -166,7 +192,8 @@
         /**
          * Checks if the caller is in the same group as the userToCheck.
          */
-        private void ensureInUserProfiles(UserHandle userToCheck, String message) {
+        @VisibleForTesting // We override it in unit tests
+        void ensureInUserProfiles(UserHandle userToCheck, String message) {
             final int callingUserId = UserHandle.getCallingUserId();
             final int targetUserId = userToCheck.getIdentifier();
 
@@ -186,12 +213,14 @@
             }
         }
 
-        private void verifyCallingPackage(String callingPackage) {
+        @VisibleForTesting // We override it in unit tests
+        void verifyCallingPackage(String callingPackage) {
             int packageUid = -1;
             try {
-                packageUid = mPm.getPackageUid(callingPackage,
+                packageUid = mPm.getPackageUidAsUser(callingPackage,
                         PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-                                | PackageManager.MATCH_UNINSTALLED_PACKAGES);
+                                | PackageManager.MATCH_UNINSTALLED_PACKAGES,
+                        UserHandle.getUserId(getCallingUid()));
             } catch (NameNotFoundException e) {
                 Log.e(TAG, "Package not found: " + callingPackage);
             }
@@ -290,17 +319,21 @@
             }
         }
 
-        private void enforceShortcutPermission(UserHandle user) {
+        private void ensureShortcutPermission(@NonNull String callingPackage, UserHandle user) {
+            verifyCallingPackage(callingPackage);
             ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
-            // STOPSHIP Implement it
+
+            if (!mShortcutServiceInternal.hasShortcutHostPermission(callingPackage,
+                    user.getIdentifier())) {
+                throw new SecurityException("Caller can't access shortcut information");
+            }
         }
 
         @Override
         public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
                 String packageName, ComponentName componentName, int flags, UserHandle user)
                 throws RemoteException {
-            enforceShortcutPermission(user);
-            verifyCallingPackage(callingPackage);
+            ensureShortcutPermission(callingPackage, user);
 
             return new ParceledListSlice<>(
                     mShortcutServiceInternal.getShortcuts(callingPackage, changedSince, packageName,
@@ -310,8 +343,7 @@
         @Override
         public ParceledListSlice getShortcutInfo(String callingPackage, String packageName,
                 List<String> ids, UserHandle user) throws RemoteException {
-            enforceShortcutPermission(user);
-            verifyCallingPackage(callingPackage);
+            ensureShortcutPermission(callingPackage, user);
 
             return new ParceledListSlice<>(
                     mShortcutServiceInternal.getShortcutInfo(callingPackage, packageName,
@@ -321,19 +353,42 @@
         @Override
         public void pinShortcuts(String callingPackage, String packageName, List<String> ids,
                 UserHandle user) throws RemoteException {
-            enforceShortcutPermission(user);
-            verifyCallingPackage(callingPackage);
+            ensureShortcutPermission(callingPackage, user);
 
             mShortcutServiceInternal.pinShortcuts(callingPackage, packageName,
                     ids, user.getIdentifier());
         }
 
         @Override
+        public int getShortcutIconResId(String callingPackage, ShortcutInfo shortcut,
+                UserHandle user) {
+            ensureShortcutPermission(callingPackage, user);
+
+            return mShortcutServiceInternal.getShortcutIconResId(callingPackage, shortcut,
+                    user.getIdentifier());
+        }
+
+        @Override
+        public ParcelFileDescriptor getShortcutIconFd(String callingPackage, ShortcutInfo shortcut,
+                UserHandle user) {
+            ensureShortcutPermission(callingPackage, user);
+
+            return mShortcutServiceInternal.getShortcutIconFd(callingPackage, shortcut,
+                    user.getIdentifier());
+        }
+
+        @Override
+        public boolean hasShortcutHostPermission(String callingPackage) throws RemoteException {
+            verifyCallingPackage(callingPackage);
+            return mShortcutServiceInternal.hasShortcutHostPermission(callingPackage,
+                    getCallingUserId());
+        }
+
+        @Override
         public boolean startShortcut(String callingPackage, String packageName, String shortcutId,
                 Rect sourceBounds, Bundle startActivityOptions, UserHandle user)
                 throws RemoteException {
-            enforceShortcutPermission(user);
-            verifyCallingPackage(callingPackage);
+            ensureShortcutPermission(callingPackage, user);
 
             final Intent intent = mShortcutServiceInternal.createShortcutIntent(callingPackage,
                     packageName, shortcutId, user.getIdentifier());
@@ -449,41 +504,44 @@
             }
         }
 
-
-        private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener {
-
-            /** Checks if user is a profile of or same as listeningUser.
-              * and the user is enabled. */
-            private boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser,
-                    String debugMsg) {
-                if (user.getIdentifier() == listeningUser.getIdentifier()) {
-                    if (DEBUG) Log.d(TAG, "Delivering msg to same user " + debugMsg);
+        /** Checks if user is a profile of or same as listeningUser.
+         * and the user is enabled. */
+        boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser,
+                String debugMsg) {
+            if (user.getIdentifier() == listeningUser.getIdentifier()) {
+                if (DEBUG) Log.d(TAG, "Delivering msg to same user " + debugMsg);
+                return true;
+            }
+            long ident = Binder.clearCallingIdentity();
+            try {
+                UserInfo userInfo = mUm.getUserInfo(user.getIdentifier());
+                UserInfo listeningUserInfo = mUm.getUserInfo(listeningUser.getIdentifier());
+                if (userInfo == null || listeningUserInfo == null
+                        || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID
+                        || userInfo.profileGroupId != listeningUserInfo.profileGroupId
+                        || !userInfo.isEnabled()) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Not delivering msg from " + user + " to " + listeningUser + ":"
+                                + debugMsg);
+                    }
+                    return false;
+                } else {
+                    if (DEBUG) {
+                        Log.d(TAG, "Delivering msg from " + user + " to " + listeningUser + ":"
+                                + debugMsg);
+                    }
                     return true;
                 }
-                long ident = Binder.clearCallingIdentity();
-                try {
-                    UserInfo userInfo = mUm.getUserInfo(user.getIdentifier());
-                    UserInfo listeningUserInfo = mUm.getUserInfo(listeningUser.getIdentifier());
-                    if (userInfo == null || listeningUserInfo == null
-                            || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID
-                            || userInfo.profileGroupId != listeningUserInfo.profileGroupId
-                            || !userInfo.isEnabled()) {
-                        if (DEBUG) {
-                            Log.d(TAG, "Not delivering msg from " + user + " to " + listeningUser + ":"
-                                    + debugMsg);
-                        }
-                        return false;
-                    } else {
-                        if (DEBUG) {
-                            Log.d(TAG, "Delivering msg from " + user + " to " + listeningUser + ":"
-                                    + debugMsg);
-                        }
-                        return true;
-                    }
-                } finally {
-                    Binder.restoreCallingIdentity(ident);
-                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
             }
+        }
+
+        void postToPackageMonitor(Runnable r) {
+            mPackageMonitor.getRegisteredHandler().post(r);
+        }
+
+        private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener {
 
             // TODO Simplify with lambdas.
 
@@ -493,8 +551,8 @@
                 final int n = mListeners.beginBroadcast();
                 for (int i = 0; i < n; i++) {
                     IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
-                    UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
-                    if (!isEnabledProfileOf(user, listeningUser, "onPackageAdded")) continue;
+                    BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+                    if (!isEnabledProfileOf(user, cookie.user, "onPackageAdded")) continue;
                     try {
                         listener.onPackageAdded(user, packageName);
                     } catch (RemoteException re) {
@@ -512,8 +570,8 @@
                 final int n = mListeners.beginBroadcast();
                 for (int i = 0; i < n; i++) {
                     IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
-                    UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
-                    if (!isEnabledProfileOf(user, listeningUser, "onPackageRemoved")) continue;
+                    BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+                    if (!isEnabledProfileOf(user, cookie.user, "onPackageRemoved")) continue;
                     try {
                         listener.onPackageRemoved(user, packageName);
                     } catch (RemoteException re) {
@@ -531,8 +589,8 @@
                 final int n = mListeners.beginBroadcast();
                 for (int i = 0; i < n; i++) {
                     IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
-                    UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
-                    if (!isEnabledProfileOf(user, listeningUser, "onPackageModified")) continue;
+                    BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+                    if (!isEnabledProfileOf(user, cookie.user, "onPackageModified")) continue;
                     try {
                         listener.onPackageChanged(user, packageName);
                     } catch (RemoteException re) {
@@ -550,8 +608,8 @@
                 final int n = mListeners.beginBroadcast();
                 for (int i = 0; i < n; i++) {
                     IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
-                    UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
-                    if (!isEnabledProfileOf(user, listeningUser, "onPackagesAvailable")) continue;
+                    BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+                    if (!isEnabledProfileOf(user, cookie.user, "onPackagesAvailable")) continue;
                     try {
                         listener.onPackagesAvailable(user, packages, isReplacing());
                     } catch (RemoteException re) {
@@ -569,8 +627,8 @@
                 final int n = mListeners.beginBroadcast();
                 for (int i = 0; i < n; i++) {
                     IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
-                    UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
-                    if (!isEnabledProfileOf(user, listeningUser, "onPackagesUnavailable")) continue;
+                    BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+                    if (!isEnabledProfileOf(user, cookie.user, "onPackagesUnavailable")) continue;
                     try {
                         listener.onPackagesUnavailable(user, packages, isReplacing());
                     } catch (RemoteException re) {
@@ -588,8 +646,8 @@
                 final int n = mListeners.beginBroadcast();
                 for (int i = 0; i < n; i++) {
                     IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
-                    UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
-                    if (!isEnabledProfileOf(user, listeningUser, "onPackagesSuspended")) continue;
+                    BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+                    if (!isEnabledProfileOf(user, cookie.user, "onPackagesSuspended")) continue;
                     try {
                         listener.onPackagesSuspended(user, packages);
                     } catch (RemoteException re) {
@@ -607,8 +665,8 @@
                 final int n = mListeners.beginBroadcast();
                 for (int i = 0; i < n; i++) {
                     IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
-                    UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
-                    if (!isEnabledProfileOf(user, listeningUser, "onPackagesUnsuspended")) continue;
+                    BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+                    if (!isEnabledProfileOf(user, cookie.user, "onPackagesUnsuspended")) continue;
                     try {
                         listener.onPackagesUnsuspended(user, packages);
                     } catch (RemoteException re) {
@@ -622,17 +680,39 @@
 
             @Override
             public void onShortcutChanged(@NonNull String packageName,
-                    @NonNull List<ShortcutInfo> shortcuts, @UserIdInt int userId) {
+                    @UserIdInt int userId) {
+                postToPackageMonitor(() -> onShortcutChangedInner(packageName, userId));
+            }
+
+            private void onShortcutChangedInner(@NonNull String packageName,
+                    @UserIdInt int userId) {
                 final UserHandle user = UserHandle.of(userId);
 
                 final int n = mListeners.beginBroadcast();
                 for (int i = 0; i < n; i++) {
                     IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
-                    UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i);
-                    if (!isEnabledProfileOf(user, listeningUser, "onShortcutChanged")) continue;
+                    BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+                    if (!isEnabledProfileOf(user, cookie.user, "onShortcutChanged")) continue;
+
+                    // Make sure the caller has the permission.
+                    if (!mShortcutServiceInternal.hasShortcutHostPermission(cookie.packageName,
+                            cookie.user.getIdentifier())) {
+                        continue;
+                    }
+                    // Each launcher has a different set of pinned shortcuts, so we need to do a
+                    // query in here.
+                    // (As of now, only one launcher has the permission at a time, so it's bit
+                    // moot, but we may change the permission model eventually.)
+                    final List<ShortcutInfo> list =
+                            mShortcutServiceInternal.getShortcuts(cookie.packageName,
+                            /* changedSince= */ 0, packageName, /* component= */ null,
+                                    ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
+                                    | ShortcutQuery.FLAG_GET_PINNED
+                                    | ShortcutQuery.FLAG_GET_DYNAMIC
+                                    , userId);
                     try {
                         listener.onShortcutChanged(user, packageName,
-                                new ParceledListSlice<>(shortcuts));
+                                new ParceledListSlice<>(list));
                     } catch (RemoteException re) {
                         Slog.d(TAG, "Callback failed ", re);
                     }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index b84ffa3..ef53905 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -34,6 +34,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageInstallObserver2;
 import android.content.pm.IPackageInstallerSession;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageInstaller.SessionInfo;
 import android.content.pm.PackageInstaller.SessionParams;
@@ -58,6 +59,7 @@
 import android.system.Os;
 import android.system.OsConstants;
 import android.system.StructStat;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.ExceptionUtils;
 import android.util.MathUtils;
@@ -77,6 +79,7 @@
 
 import java.io.File;
 import java.io.FileDescriptor;
+import java.io.FileFilter;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -86,6 +89,7 @@
 public class PackageInstallerSession extends IPackageInstallerSession.Stub {
     private static final String TAG = "PackageInstaller";
     private static final boolean LOGD = true;
+    private static final String REMOVE_SPLIT_MARKER_EXTENSION = ".removed";
 
     private static final int MSG_COMMIT = 0;
 
@@ -171,6 +175,25 @@
     @GuardedBy("mLock")
     private File mInheritedFilesBase;
 
+    private static final FileFilter sAddedFilter = new FileFilter() {
+        @Override
+        public boolean accept(File file) {
+            // Installers can't stage directories, so it's fine to ignore
+            // entries like "lost+found".
+            if (file.isDirectory()) return false;
+            if (file.getName().endsWith(REMOVE_SPLIT_MARKER_EXTENSION)) return false;
+            return true;
+        }
+    };
+    private static final FileFilter sRemovedFilter = new FileFilter() {
+        @Override
+        public boolean accept(File file) {
+            if (file.isDirectory()) return false;
+            if (!file.getName().endsWith(REMOVE_SPLIT_MARKER_EXTENSION)) return false;
+            return true;
+        }
+    };
+
     private final Handler.Callback mHandlerCallback = new Handler.Callback() {
         @Override
         public boolean handleMessage(Message msg) {
@@ -346,6 +369,32 @@
     }
 
     @Override
+    public void removeSplit(String splitName) {
+        if (TextUtils.isEmpty(params.appPackageName)) {
+            throw new IllegalStateException("Must specify package name to remove a split");
+        }
+        try {
+            createRemoveSplitMarker(splitName);
+        } catch (IOException e) {
+            throw ExceptionUtils.wrap(e);
+        }
+    }
+
+    private void createRemoveSplitMarker(String splitName) throws IOException {
+        try {
+            final String markerName = splitName + REMOVE_SPLIT_MARKER_EXTENSION;
+            if (!FileUtils.isValidExtFilename(markerName)) {
+                throw new IllegalArgumentException("Invalid marker: " + markerName);
+            }
+            final File target = new File(resolveStageDir(), markerName);
+            target.createNewFile();
+            Os.chmod(target.getAbsolutePath(), 0 /*mode*/);
+        } catch (ErrnoException e) {
+            throw e.rethrowAsIOException();
+        }
+    }
+
+    @Override
     public ParcelFileDescriptor openWrite(String name, long offsetBytes, long lengthBytes) {
         try {
             return openWriteInternal(name, offsetBytes, lengthBytes);
@@ -608,22 +657,28 @@
         mResolvedStagedFiles.clear();
         mResolvedInheritedFiles.clear();
 
-        final File[] files = mResolvedStageDir.listFiles();
-        if (ArrayUtils.isEmpty(files)) {
-            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
+        final File[] removedFiles = mResolvedStageDir.listFiles(sRemovedFilter);
+        final List<String> removeSplitList = new ArrayList<>();
+        if (!ArrayUtils.isEmpty(removedFiles)) {
+            for (File removedFile : removedFiles) {
+                final String fileName = removedFile.getName();
+                final String splitName = fileName.substring(
+                        0, fileName.length() - REMOVE_SPLIT_MARKER_EXTENSION.length());
+                removeSplitList.add(splitName);
+            }
         }
 
+        final File[] addedFiles = mResolvedStageDir.listFiles(sAddedFilter);
+        if (ArrayUtils.isEmpty(addedFiles) && removeSplitList.size() == 0) {
+            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
+        }
         // Verify that all staged packages are internally consistent
         final ArraySet<String> stagedSplits = new ArraySet<>();
-        for (File file : files) {
-
-            // Installers can't stage directories, so it's fine to ignore
-            // entries like "lost+found".
-            if (file.isDirectory()) continue;
-
+        for (File addedFile : addedFiles) {
             final ApkLite apk;
             try {
-                apk = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES);
+                apk = PackageParser.parseApkLite(
+                        addedFile, PackageParser.PARSE_COLLECT_CERTIFICATES);
             } catch (PackageParserException e) {
                 throw PackageManagerException.from(e);
             }
@@ -642,7 +697,7 @@
                 mSignatures = apk.signatures;
             }
 
-            assertApkConsistent(String.valueOf(file), apk);
+            assertApkConsistent(String.valueOf(addedFile), apk);
 
             // Take this opportunity to enforce uniform naming
             final String targetName;
@@ -657,8 +712,8 @@
             }
 
             final File targetFile = new File(mResolvedStageDir, targetName);
-            if (!file.equals(targetFile)) {
-                file.renameTo(targetFile);
+            if (!addedFile.equals(targetFile)) {
+                addedFile.renameTo(targetFile);
             }
 
             // Base is coming from session
@@ -669,6 +724,27 @@
             mResolvedStagedFiles.add(targetFile);
         }
 
+        if (removeSplitList.size() > 0) {
+            // validate split names marked for removal
+            final int flags = mSignatures == null ? PackageManager.GET_SIGNATURES : 0;
+            final PackageInfo pkg = mPm.getPackageInfo(params.appPackageName, flags, userId);
+            for (String splitName : removeSplitList) {
+                if (!ArrayUtils.contains(pkg.splitNames, splitName)) {
+                    throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+                            "Split not found: " + splitName);
+                }
+            }
+
+            // ensure we've got appropriate package name, version code and signatures
+            if (mPackageName == null) {
+                mPackageName = pkg.packageName;
+                mVersionCode = pkg.versionCode;
+            }
+            if (mSignatures == null) {
+                mSignatures = pkg.signatures;
+            }
+        }
+
         if (params.mode == SessionParams.MODE_FULL_INSTALL) {
             // Full installs must include a base package
             if (!stagedSplits.contains(null)) {
@@ -707,8 +783,8 @@
                 for (int i = 0; i < existing.splitNames.length; i++) {
                     final String splitName = existing.splitNames[i];
                     final File splitFile = new File(existing.splitCodePaths[i]);
-
-                    if (!stagedSplits.contains(splitName)) {
+                    final boolean splitRemoved = removeSplitList.contains(splitName);
+                    if (!stagedSplits.contains(splitName) && !splitRemoved) {
                         mResolvedInheritedFiles.add(splitFile);
                     }
                 }
@@ -748,6 +824,11 @@
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " package "
                     + apk.packageName + " inconsistent with " + mPackageName);
         }
+        if (params.appPackageName != null && !params.appPackageName.equals(apk.packageName)) {
+            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag
+                    + " specified package " + params.appPackageName
+                    + " inconsistent with " + apk.packageName);
+        }
         if (mVersionCode != apk.versionCode) {
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag
                     + " version code " + apk.versionCode + " inconsistent with "
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index debe072..c7578f0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -6891,7 +6891,8 @@
 
         // Extract pacakges only if profile-guided compilation is enabled because
         // otherwise BackgroundDexOptService will not dexopt them later.
-        if (!isUpgrade()) {
+        boolean prunedCache = VMRuntime.didPruneDalvikCache();
+        if (!isUpgrade() && !prunedCache) {
             return;
         }
 
@@ -6919,8 +6920,11 @@
             }
 
             if (PackageDexOptimizer.canOptimizePackage(pkg)) {
+                // If the cache was pruned, any compiled odex files will likely be out of date
+                // and would have to be patched (would be SELF_PATCHOAT, which is deprecated).
+                // Instead, force the extraction in this case.
                 performDexOpt(pkg.packageName, null /* instructionSet */,
-                         false /* useProfiles */, true /* extractOnly */, false /* force */);
+                         false /* useProfiles */, true /* extractOnly */, prunedCache);
             }
         }
     }
@@ -10822,25 +10826,41 @@
         }
     }
 
-    // TODO: investigate and add more restrictions for suspending crucial packages.
+    /**
+     * TODO: cache and disallow blocking the active dialer.
+     *
+     * @see also DefaultPermissionGrantPolicy#grantDefaultSystemHandlerPermissions
+     */
     private boolean canSuspendPackageForUserLocked(String packageName, int userId) {
         if (isPackageDeviceAdmin(packageName, userId)) {
-            Slog.w(TAG, "Not suspending/un-suspending package \"" + packageName
-                    + "\": has active device admin");
+            Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
+                    + "\": has an active device admin");
             return false;
         }
 
         String activeLauncherPackageName = getActiveLauncherPackageName(userId);
         if (packageName.equals(activeLauncherPackageName)) {
-            Slog.w(TAG, "Not suspending/un-suspending package \"" + packageName
-                    + "\" because it is set as the active launcher");
+            Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
+                    + "\": contains the active launcher");
+            return false;
+        }
+
+        if (packageName.equals(mRequiredInstallerPackage)) {
+            Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
+                    + "\": required for package installation");
+            return false;
+        }
+
+        if (packageName.equals(mRequiredVerifierPackage)) {
+            Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
+                    + "\": required for package verification");
             return false;
         }
 
         final PackageParser.Package pkg = mPackages.get(packageName);
         if (pkg != null && isPrivilegedApp(pkg)) {
-            Slog.w(TAG, "Not suspending/un-suspending package \"" + packageName
-                    + "\" because it is a privileged app");
+            Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
+                    + "\": is a privileged app");
             return false;
         }
 
@@ -16436,14 +16456,29 @@
 
     @Override
     public ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) {
+        return getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getCallingUserId());
+    }
+
+    private Intent getHomeIntent() {
         Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.addCategory(Intent.CATEGORY_HOME);
+        return intent;
+    }
 
-        final int callingUserId = UserHandle.getCallingUserId();
+    private IntentFilter getHomeFilter() {
+        IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
+        filter.addCategory(Intent.CATEGORY_HOME);
+        filter.addCategory(Intent.CATEGORY_DEFAULT);
+        return filter;
+    }
+
+    ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
+            int userId) {
+        Intent intent  = getHomeIntent();
         List<ResolveInfo> list = queryIntentActivitiesInternal(intent, null,
-                PackageManager.GET_META_DATA, callingUserId);
+                PackageManager.GET_META_DATA, userId);
         ResolveInfo preferred = findPreferredActivity(intent, null, 0, list, 0,
-                true, false, false, callingUserId);
+                true, false, false, userId);
 
         allHomeCandidates.clear();
         if (list != null) {
@@ -16458,6 +16493,32 @@
     }
 
     @Override
+    public void setHomeActivity(ComponentName comp, int userId) {
+        ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
+        getHomeActivitiesAsUser(homeActivities, userId);
+
+        boolean found = false;
+
+        final int size = homeActivities.size();
+        final ComponentName[] set = new ComponentName[size];
+        for (int i = 0; i < size; i++) {
+            final ResolveInfo candidate = homeActivities.get(i);
+            final ActivityInfo info = candidate.activityInfo;
+            final ComponentName activityName = new ComponentName(info.packageName, info.name);
+            set[i] = activityName;
+            if (!found && activityName.equals(comp)) {
+                found = true;
+            }
+        }
+        if (!found) {
+            throw new IllegalArgumentException("Component " + comp + " cannot be home on user "
+                    + userId);
+        }
+        replacePreferredActivity(getHomeFilter(), IntentFilter.MATCH_CATEGORY_EMPTY,
+                set, comp, userId);
+    }
+
+    @Override
     public void setApplicationEnabledSetting(String appPackageName,
             int newState, int flags, int userId, String callingPackage) {
         if (!sUserManager.exists(userId)) return;
@@ -16601,6 +16662,22 @@
         }
     }
 
+    @Override
+    public void flushPackageRestrictionsAsUser(int userId) {
+        if (!sUserManager.exists(userId)) {
+            return;
+        }
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false /* requireFullPermission*/,
+                false /* checkShell */, "flushPackageRestrictions");
+        synchronized (mPackages) {
+            mSettings.writePackageRestrictionsLPr(userId);
+            mDirtyUsers.remove(userId);
+            if (mDirtyUsers.isEmpty()) {
+                mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
+            }
+        }
+    }
+
     private void sendPackageChangedBroadcast(String packageName,
             boolean killFlag, ArrayList<String> componentNames, int packageUid) {
         if (DEBUG_INSTALL)
@@ -19232,6 +19309,12 @@
         public ApplicationInfo getApplicationInfo(String packageName, int userId) {
             return PackageManagerService.this.getApplicationInfo(packageName, 0 /*flags*/, userId);
         }
+
+        @Override
+        public ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
+                int userId) {
+            return PackageManagerService.this.getHomeActivitiesAsUser(allHomeCandidates, userId);
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 28d34a8..319fc37 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -95,6 +95,8 @@
                     return runInstallCommit();
                 case "install-create":
                     return runInstallCreate();
+                case "install-remove":
+                    return runInstallRemove();
                 case "install-write":
                     return runInstallWrite();
                 case "compile":
@@ -115,6 +117,8 @@
                     return runSuspend(true);
                 case "unsuspend":
                     return runSuspend(false);
+                case "set-home-activity":
+                    return runSetHomeActivity();
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -136,11 +140,12 @@
                 pw.println("Error: must either specify a package size or an APK file");
                 return 1;
             }
-            if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
+            if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
                     false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
                 return 1;
             }
-            if (doCommitSession(sessionId, false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
+            if (doCommitSession(sessionId, false /*logSuccess*/)
+                    != PackageInstaller.STATUS_SUCCESS) {
                 return 1;
             }
             abandonSession = false;
@@ -225,7 +230,20 @@
         final int sessionId = Integer.parseInt(getNextArg());
         final String splitName = getNextArg();
         final String path = getNextArg();
-        return doWriteSession(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
+        return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
+    }
+
+    private int runInstallRemove() throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+
+        final int sessionId = Integer.parseInt(getNextArg());
+
+        final String splitName = getNextArg();
+        if (splitName == null) {
+            pw.println("Error: split name not specified");
+            return 1;
+        }
+        return doRemoveSplit(sessionId, splitName, true /*logSuccess*/);
     }
 
     private int runCompile() throws RemoteException {
@@ -666,12 +684,18 @@
             }
         }
 
-        String packageName = getNextArg();
+        final String packageName = getNextArg();
         if (packageName == null) {
             pw.println("Error: package name not specified");
             return 1;
         }
 
+        // if a split is specified, just remove it and not the whole package
+        final String splitName = getNextArg();
+        if (splitName != null) {
+            return runRemoveSplit(packageName, splitName);
+        }
+
         userId = translateUserId(userId, "runUninstall");
         if (userId == UserHandle.USER_ALL) {
             userId = UserHandle.USER_SYSTEM;
@@ -709,6 +733,36 @@
         }
     }
 
+    private int runRemoveSplit(String packageName, String splitName) throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+        final SessionParams sessionParams = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
+        sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
+        sessionParams.appPackageName = packageName;
+        final int sessionId =
+                doCreateSession(sessionParams, null /*installerPackageName*/, UserHandle.USER_ALL);
+        boolean abandonSession = true;
+        try {
+            if (doRemoveSplit(sessionId, splitName, false /*logSuccess*/)
+                    != PackageInstaller.STATUS_SUCCESS) {
+                return 1;
+            }
+            if (doCommitSession(sessionId, false /*logSuccess*/)
+                    != PackageInstaller.STATUS_SUCCESS) {
+                return 1;
+            }
+            abandonSession = false;
+            pw.println("Success");
+            return 0;
+        } finally {
+            if (abandonSession) {
+                try {
+                    doAbandonSession(sessionId, false /*logSuccess*/);
+                } catch (Exception ignore) {
+                }
+            }
+        }
+    }
+
     private Intent parseIntentAndUser() throws URISyntaxException {
         mTargetUser = UserHandle.USER_CURRENT;
         Intent intent = Intent.parseCommandArgs(this, new Intent.CommandOptionHandler() {
@@ -911,6 +965,39 @@
         return params;
     }
 
+    private int runSetHomeActivity() {
+        final PrintWriter pw = getOutPrintWriter();
+        int userId = UserHandle.USER_SYSTEM;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+                default:
+                    pw.println("Error: Unknown option: " + opt);
+                    return 1;
+            }
+        }
+
+        String component = getNextArg();
+        ComponentName componentName =
+                component != null ? ComponentName.unflattenFromString(component) : null;
+
+        if (componentName == null) {
+            pw.println("Error: component name not specified or invalid");
+            return 1;
+        }
+
+        try {
+            mInterface.setHomeActivity(componentName, userId);
+            return 0;
+        } catch (RemoteException e) {
+            pw.println(e.toString());
+            return 1;
+        }
+    }
+
     private static String checkAbiArgument(String abi) {
         if (TextUtils.isEmpty(abi)) {
             throw new IllegalArgumentException("Missing ABI argument");
@@ -948,7 +1035,7 @@
         return sessionId;
     }
 
-    private int doWriteSession(int sessionId, String inPath, long sizeBytes, String splitName,
+    private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
             boolean logSuccess) throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         if ("-".equals(inPath)) {
@@ -1004,6 +1091,27 @@
         }
     }
 
+    private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess)
+            throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+        PackageInstaller.Session session = null;
+        try {
+            session = new PackageInstaller.Session(
+                    mInterface.getPackageInstaller().openSession(sessionId));
+            session.removeSplit(splitName);
+
+            if (logSuccess) {
+                pw.println("Success");
+            }
+            return 0;
+        } catch (IOException e) {
+            pw.println("Error: failed to remove split; " + e.getMessage());
+            return 1;
+        } finally {
+            IoUtils.closeQuietly(session);
+        }
+    }
+
     private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
         PackageInstaller.Session session = null;
@@ -1230,6 +1338,8 @@
         pw.println("    Suspends the specified package (as user).");
         pw.println("  unsuspend [--user USER_ID] TARGET-PACKAGE");
         pw.println("    Unsuspends the specified package (as user).");
+        pw.println("  set-home-activity [--user USER_ID] TARGET-COMPONENT");
+        pw.println("    set the default home activity (aka launcher).");
         pw.println();
         Intent.printIntentArgsHelp(pw , "");
     }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index bf5a8f6..4c77f28 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4291,6 +4291,7 @@
         }
         pw.print(prefix); pw.print("  versionCode="); pw.print(ps.versionCode);
         if (ps.pkg != null) {
+            pw.print(" minSdk="); pw.print(ps.pkg.applicationInfo.minSdkVersion);
             pw.print(" targetSdk="); pw.print(ps.pkg.applicationInfo.targetSdkVersion);
         }
         pw.println();
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 423767a..0641749 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -18,7 +18,9 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
+import android.app.ActivityManager;
 import android.content.ComponentName;
+import android.content.ContentProvider;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.IShortcutService;
@@ -26,28 +28,40 @@
 import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ParceledListSlice;
+import android.content.pm.ResolveInfo;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutServiceInternal;
 import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.RectF;
 import android.graphics.drawable.Icon;
+import android.net.Uri;
 import android.os.Binder;
-import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
+import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.SELinux;
 import android.os.ShellCommand;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.text.format.Formatter;
 import android.text.format.Time;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
+import android.util.KeyValueListParser;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.TypedValue;
 import android.util.Xml;
 
 import com.android.internal.annotations.GuardedBy;
@@ -59,6 +73,7 @@
 import com.android.server.SystemService;
 
 import libcore.io.IoUtils;
+import libcore.util.Objects;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -70,6 +85,7 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintWriter;
 import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
@@ -79,29 +95,48 @@
 
 /**
  * TODO:
- * - Make save async
  *
- * - Add Bitmap support
- *
- * - Implement updateShortcuts
+ * - Detect when already registered instances are passed to APIs again, which might break
+ *   internal bitmap handling.
  *
  * - Listen to PACKAGE_*, remove orphan info, update timestamp for icon res
+ *   -> Need to scan all packages when a user starts too.
+ *   -> Clear data -> remove all dynamic?  but not the pinned?
  *
  * - Pinned per each launcher package (multiple launchers)
  *
- * - Dev option to reset all counts for QA (for now use "adb shell cmd shortcut reset-throttling")
+ * - Make save async (should we?)
  *
- * - Load config from settings
+ * - Scan and remove orphan bitmaps (just in case).
+ *
+ * - Backup & restore
  */
 public class ShortcutService extends IShortcutService.Stub {
-    private static final String TAG = "ShortcutService";
+    static final String TAG = "ShortcutService";
 
-    private static final boolean DEBUG = true; // STOPSHIP if true
-    private static final boolean DEBUG_LOAD = true; // STOPSHIP if true
+    static final boolean DEBUG = false; // STOPSHIP if true
+    static final boolean DEBUG_LOAD = false; // STOPSHIP if true
 
-    private static final int DEFAULT_RESET_INTERVAL_SEC = 24 * 60 * 60; // 1 day
-    private static final int DEFAULT_MAX_DAILY_UPDATES = 10;
-    private static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 5;
+    @VisibleForTesting
+    static final long DEFAULT_RESET_INTERVAL_SEC = 24 * 60 * 60; // 1 day
+
+    @VisibleForTesting
+    static final int DEFAULT_MAX_DAILY_UPDATES = 10;
+
+    @VisibleForTesting
+    static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 5;
+
+    @VisibleForTesting
+    static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;
+
+    @VisibleForTesting
+    static final int DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP = 48;
+
+    @VisibleForTesting
+    static final String DEFAULT_ICON_PERSIST_FORMAT = CompressFormat.PNG.name();
+
+    @VisibleForTesting
+    static final int DEFAULT_ICON_PERSIST_QUALITY = 100;
 
     private static final int SAVE_DELAY_MS = 5000; // in milliseconds.
 
@@ -114,13 +149,71 @@
     @VisibleForTesting
     static final String FILENAME_USER_PACKAGES = "shortcuts.xml";
 
-    private static final String DIRECTORY_BITMAPS = "bitmaps";
+    static final String DIRECTORY_BITMAPS = "bitmaps";
 
-    private static final String TAG_ROOT = "root";
-    private static final String TAG_LAST_RESET_TIME = "last_reset_time";
-    private static final String ATTR_VALUE = "value";
+    static final String TAG_ROOT = "root";
+    static final String TAG_USER = "user";
+    static final String TAG_PACKAGE = "package";
+    static final String TAG_LAST_RESET_TIME = "last_reset_time";
+    static final String TAG_INTENT_EXTRAS = "intent-extras";
+    static final String TAG_EXTRAS = "extras";
+    static final String TAG_SHORTCUT = "shortcut";
+    static final String TAG_LAUNCHER = "launcher";
 
-    private final Context mContext;
+    static final String ATTR_VALUE = "value";
+    static final String ATTR_NAME = "name";
+    static final String ATTR_DYNAMIC_COUNT = "dynamic-count";
+    static final String ATTR_CALL_COUNT = "call-count";
+    static final String ATTR_LAST_RESET = "last-reset";
+    static final String ATTR_ID = "id";
+    static final String ATTR_ACTIVITY = "activity";
+    static final String ATTR_TITLE = "title";
+    static final String ATTR_INTENT = "intent";
+    static final String ATTR_WEIGHT = "weight";
+    static final String ATTR_TIMESTAMP = "timestamp";
+    static final String ATTR_FLAGS = "flags";
+    static final String ATTR_ICON_RES = "icon-res";
+    static final String ATTR_BITMAP_PATH = "bitmap-path";
+
+    @VisibleForTesting
+    interface ConfigConstants {
+        /**
+         * Key name for the throttling reset interval, in seconds. (long)
+         */
+        String KEY_RESET_INTERVAL_SEC = "reset_interval_sec";
+
+        /**
+         * Key name for the max number of modifying API calls per app for every interval. (int)
+         */
+        String KEY_MAX_DAILY_UPDATES = "max_daily_updates";
+
+        /**
+         * Key name for the max icon dimensions in DP, for non-low-memory devices.
+         */
+        String KEY_MAX_ICON_DIMENSION_DP = "max_icon_dimension_dp";
+
+        /**
+         * Key name for the max icon dimensions in DP, for low-memory devices.
+         */
+        String KEY_MAX_ICON_DIMENSION_DP_LOWRAM = "max_icon_dimension_dp_lowram";
+
+        /**
+         * Key name for the max dynamic shortcuts per app. (int)
+         */
+        String KEY_MAX_SHORTCUTS = "max_shortcuts";
+
+        /**
+         * Key name for icon compression quality, 0-100.
+         */
+        String KEY_ICON_QUALITY = "icon_quality";
+
+        /**
+         * Key name for icon compression format: "PNG", "JPEG" or "WEBP"
+         */
+        String KEY_ICON_FORMAT = "icon_format";
+    }
+
+    final Context mContext;
 
     private final Object mLock = new Object();
 
@@ -133,205 +226,41 @@
     private long mRawLastResetTime;
 
     /**
-     * All the information relevant to shortcuts from a single package (per-user).
-     *
-     * TODO Move the persisting code to this class.
-     */
-    private static class PackageShortcuts {
-        /**
-         * All the shortcuts from the package, keyed on IDs.
-         */
-        final private ArrayMap<String, ShortcutInfo> mShortcuts = new ArrayMap<>();
-
-        /**
-         * # of dynamic shortcuts.
-         */
-        private int mDynamicShortcutCount = 0;
-
-        /**
-         * # of times the package has called rate-limited APIs.
-         */
-        private int mApiCallCountInner;
-
-        /**
-         * When {@link #mApiCallCountInner} was reset last time.
-         */
-        private long mLastResetTime;
-
-        /**
-         * @return the all shortcuts.  Note DO NOT add/remove or touch the flags of the result
-         * directly, which would cause {@link #mDynamicShortcutCount} to be out of sync.
-         */
-        @GuardedBy("mLock")
-        public ArrayMap<String, ShortcutInfo> getShortcuts() {
-            return mShortcuts;
-        }
-
-        /**
-         * Add a shortcut, or update one with the same ID, with taking over existing flags.
-         *
-         * It checks the max number of dynamic shortcuts.
-         */
-        @GuardedBy("mLock")
-        public void updateShortcutWithCapping(@NonNull ShortcutService s,
-                @NonNull ShortcutInfo newShortcut) {
-            final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
-
-            int oldFlags = 0;
-            int newDynamicCount = mDynamicShortcutCount;
-
-            if (oldShortcut != null) {
-                oldFlags = oldShortcut.getFlags();
-                if (oldShortcut.isDynamic()) {
-                    newDynamicCount--;
-                }
-            }
-            if (newShortcut.isDynamic()) {
-                newDynamicCount++;
-            }
-            // Make sure there's still room.
-            s.enforceMaxDynamicShortcuts(newDynamicCount);
-
-            // Okay, make it dynamic and add.
-            newShortcut.addFlags(oldFlags);
-
-            mShortcuts.put(newShortcut.getId(), newShortcut);
-            mDynamicShortcutCount = newDynamicCount;
-        }
-
-        @GuardedBy("mLock")
-        public void deleteAllDynamicShortcuts() {
-            ArrayList<String> removeList = null; // Lazily initialize.
-
-            for (int i = mShortcuts.size() - 1; i >= 0; i--) {
-                final ShortcutInfo si = mShortcuts.valueAt(i);
-
-                if (!si.isDynamic()) {
-                    continue;
-                }
-                if (si.isPinned()) {
-                    // Still pinned, so don't remove; just make it non-dynamic.
-                    si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
-                } else {
-                    if (removeList == null) {
-                        removeList = new ArrayList<>();
-                    }
-                    removeList.add(si.getId());
-                }
-            }
-            if (removeList != null) {
-                for (int i = removeList.size() - 1 ; i >= 0; i--) {
-                    mShortcuts.remove(removeList.get(i));
-                }
-            }
-            mDynamicShortcutCount = 0;
-        }
-
-        @GuardedBy("mLock")
-        public void deleteDynamicWithId(@NonNull String shortcutId) {
-            final ShortcutInfo oldShortcut = mShortcuts.get(shortcutId);
-
-            if (oldShortcut == null) {
-                return;
-            }
-            if (oldShortcut.isDynamic()) {
-                mDynamicShortcutCount--;
-            }
-            if (oldShortcut.isPinned()) {
-                oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
-            } else {
-                mShortcuts.remove(shortcutId);
-            }
-        }
-
-        @GuardedBy("mLock")
-        public void pinAll(List<String> shortcutIds) {
-            for (int i = shortcutIds.size() - 1; i >= 0; i--) {
-                final ShortcutInfo shortcut = mShortcuts.get(shortcutIds.get(i));
-                if (shortcut != null) {
-                    shortcut.addFlags(ShortcutInfo.FLAG_PINNED);
-                }
-            }
-        }
-
-        /**
-         * Number of calls that the caller has made, since the last reset.
-         */
-        @GuardedBy("mLock")
-        public int getApiCallCount(@NonNull ShortcutService s) {
-            final long last = s.getLastResetTimeLocked();
-
-            // If not reset yet, then reset.
-            if (mLastResetTime < last) {
-                mApiCallCountInner = 0;
-                mLastResetTime = last;
-            }
-            return mApiCallCountInner;
-        }
-
-        /**
-         * If the caller app hasn't been throttled yet, increment {@link #mApiCallCountInner}
-         * and return true.  Otherwise just return false.
-         */
-        @GuardedBy("mLock")
-        public boolean tryApiCall(@NonNull ShortcutService s) {
-            if (getApiCallCount(s) >= s.mMaxDailyUpdates) {
-                return false;
-            }
-            mApiCallCountInner++;
-            return true;
-        }
-
-        @GuardedBy("mLock")
-        public void resetRateLimitingForCommandLine() {
-            mApiCallCountInner = 0;
-            mLastResetTime = 0;
-        }
-
-        /**
-         * Find all shortcuts that match {@code query}.
-         */
-        @GuardedBy("mLock")
-        public void findAll(@NonNull List<ShortcutInfo> result,
-                @Nullable Predicate<ShortcutInfo> query, int cloneFlag) {
-            for (int i = 0; i < mShortcuts.size(); i++) {
-                final ShortcutInfo si = mShortcuts.valueAt(i);
-                if (query == null || query.test(si)) {
-                    result.add(si.clone(cloneFlag));
-                }
-            }
-        }
-    }
-
-    /**
-     * User ID -> package name -> list of ShortcutInfos.
+     * User ID -> UserShortcuts
      */
     @GuardedBy("mLock")
-    private final SparseArray<ArrayMap<String, PackageShortcuts>> mShortcuts =
-            new SparseArray<>();
+    private final SparseArray<UserShortcuts> mUsers = new SparseArray<>();
 
     /**
      * Max number of dynamic shortcuts that each application can have at a time.
      */
-    @GuardedBy("mLock")
     private int mMaxDynamicShortcuts;
 
     /**
      * Max number of updating API calls that each application can make a day.
      */
-    @GuardedBy("mLock")
-    private int mMaxDailyUpdates;
+    int mMaxDailyUpdates;
 
     /**
      * Actual throttling-reset interval.  By default it's a day.
      */
-    @GuardedBy("mLock")
     private long mResetInterval;
 
+    /**
+     * Icon max width/height in pixels.
+     */
+    private int mMaxIconDimension;
+
+    private CompressFormat mIconPersistFormat;
+    private int mIconPersistQuality;
+
+    private final PackageManagerInternal mPackageManagerInternal;
+
     public ShortcutService(Context context) {
         mContext = Preconditions.checkNotNull(context);
         LocalServices.addService(ShortcutServiceInternal.class, new LocalService());
         mHandler = new Handler(BackgroundThread.get().getLooper());
+        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
     }
 
     /**
@@ -363,7 +292,7 @@
         }
 
         @Override
-        public void onStartUser(int userId) {
+        public void onUnlockUser(int userId) {
             synchronized (mService.mLock) {
                 mService.onStartUserLocked(userId);
             }
@@ -391,7 +320,7 @@
     /** lifecycle event */
     void onCleanupUserInner(int userId) {
         // Unload
-        mShortcuts.delete(userId);
+        mUsers.delete(userId);
     }
 
     /** Return the base state file name */
@@ -406,27 +335,90 @@
      */
     private void initialize() {
         synchronized (mLock) {
-            injectLoadConfigurationLocked();
+            loadConfigurationLocked();
             loadBaseStateLocked();
         }
     }
 
-    // Test overrides it to inject different values.
-    @VisibleForTesting
-    void injectLoadConfigurationLocked() {
-        mResetInterval = DEFAULT_RESET_INTERVAL_SEC * 1000L;
-        mMaxDailyUpdates = DEFAULT_MAX_DAILY_UPDATES;
-        mMaxDynamicShortcuts = DEFAULT_MAX_SHORTCUTS_PER_APP;
+    /**
+     * Load the configuration from Settings.
+     */
+    private void loadConfigurationLocked() {
+        updateConfigurationLocked(injectShortcutManagerConstants());
     }
 
-    // === Persistings ===
+    /**
+     * Load the configuration from Settings.
+     */
+    @VisibleForTesting
+    boolean updateConfigurationLocked(String config) {
+        boolean result = true;
+
+        final KeyValueListParser parser = new KeyValueListParser(',');
+        try {
+            parser.setString(config);
+        } catch (IllegalArgumentException e) {
+            // Failed to parse the settings string, log this and move on
+            // with defaults.
+            Slog.e(TAG, "Bad shortcut manager settings", e);
+            result = false;
+        }
+
+        mResetInterval = parser.getLong(
+                ConfigConstants.KEY_RESET_INTERVAL_SEC, DEFAULT_RESET_INTERVAL_SEC)
+                * 1000L;
+
+        mMaxDailyUpdates = (int) parser.getLong(
+                ConfigConstants.KEY_MAX_DAILY_UPDATES, DEFAULT_MAX_DAILY_UPDATES);
+
+        mMaxDynamicShortcuts = (int) parser.getLong(
+                ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_APP);
+
+        final int iconDimensionDp = injectIsLowRamDevice()
+                ? (int) parser.getLong(
+                    ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
+                    DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP)
+                : (int) parser.getLong(
+                    ConfigConstants.KEY_MAX_ICON_DIMENSION_DP,
+                    DEFAULT_MAX_ICON_DIMENSION_DP);
+
+        mMaxIconDimension = injectDipToPixel(iconDimensionDp);
+
+        mIconPersistFormat = CompressFormat.valueOf(
+                parser.getString(ConfigConstants.KEY_ICON_FORMAT, DEFAULT_ICON_PERSIST_FORMAT));
+
+        mIconPersistQuality = (int) parser.getLong(
+                ConfigConstants.KEY_ICON_QUALITY,
+                DEFAULT_ICON_PERSIST_QUALITY);
+
+        return result;
+    }
+
+    @VisibleForTesting
+    String injectShortcutManagerConstants() {
+        return android.provider.Settings.Global.getString(
+                mContext.getContentResolver(),
+                android.provider.Settings.Global.SHORTCUT_MANAGER_CONSTANTS);
+    }
+
+    @VisibleForTesting
+    int injectDipToPixel(int dip) {
+        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip,
+                mContext.getResources().getDisplayMetrics());
+    }
+
+    // === Persisting ===
 
     @Nullable
-    private String parseStringAttribute(XmlPullParser parser, String attribute) {
+    static String parseStringAttribute(XmlPullParser parser, String attribute) {
         return parser.getAttributeValue(null, attribute);
     }
 
-    private long parseLongAttribute(XmlPullParser parser, String attribute) {
+    static int parseIntAttribute(XmlPullParser parser, String attribute) {
+        return (int) parseLongAttribute(parser, attribute);
+    }
+
+    static long parseLongAttribute(XmlPullParser parser, String attribute) {
         final String value = parseStringAttribute(parser, attribute);
         if (TextUtils.isEmpty(value)) {
             return 0;
@@ -440,7 +432,7 @@
     }
 
     @Nullable
-    private ComponentName parseComponentNameAttribute(XmlPullParser parser, String attribute) {
+    static ComponentName parseComponentNameAttribute(XmlPullParser parser, String attribute) {
         final String value = parseStringAttribute(parser, attribute);
         if (TextUtils.isEmpty(value)) {
             return null;
@@ -449,7 +441,7 @@
     }
 
     @Nullable
-    private Intent parseIntentAttribute(XmlPullParser parser, String attribute) {
+    static Intent parseIntentAttribute(XmlPullParser parser, String attribute) {
         final String value = parseStringAttribute(parser, attribute);
         if (TextUtils.isEmpty(value)) {
             return null;
@@ -462,7 +454,7 @@
         }
     }
 
-    private void writeTagValue(XmlSerializer out, String tag, String value) throws IOException {
+    static void writeTagValue(XmlSerializer out, String tag, String value) throws IOException {
         if (TextUtils.isEmpty(value)) return;
 
         out.startTag(null, tag);
@@ -470,11 +462,16 @@
         out.endTag(null, tag);
     }
 
-    private void writeTagValue(XmlSerializer out, String tag, long value) throws IOException {
+    static void writeTagValue(XmlSerializer out, String tag, long value) throws IOException {
         writeTagValue(out, tag, Long.toString(value));
     }
 
-    private void writeTagExtra(XmlSerializer out, String tag, PersistableBundle bundle)
+    static void writeTagValue(XmlSerializer out, String tag, ComponentName name) throws IOException {
+        if (name == null) return;
+        writeTagValue(out, tag, name.flattenToString());
+    }
+
+    static void writeTagExtra(XmlSerializer out, String tag, PersistableBundle bundle)
             throws IOException, XmlPullParserException {
         if (bundle == null) return;
 
@@ -483,22 +480,22 @@
         out.endTag(null, tag);
     }
 
-    private void writeAttr(XmlSerializer out, String name, String value) throws IOException {
+    static void writeAttr(XmlSerializer out, String name, String value) throws IOException {
         if (TextUtils.isEmpty(value)) return;
 
         out.attribute(null, name, value);
     }
 
-    private void writeAttr(XmlSerializer out, String name, long value) throws IOException {
+    static void writeAttr(XmlSerializer out, String name, long value) throws IOException {
         writeAttr(out, name, String.valueOf(value));
     }
 
-    private void writeAttr(XmlSerializer out, String name, ComponentName comp) throws IOException {
+    static void writeAttr(XmlSerializer out, String name, ComponentName comp) throws IOException {
         if (comp == null) return;
         writeAttr(out, name, comp.flattenToString());
     }
 
-    private void writeAttr(XmlSerializer out, String name, Intent intent) throws IOException {
+    static void writeAttr(XmlSerializer out, String name, Intent intent) throws IOException {
         if (intent == null) return;
 
         writeAttr(out, name, intent.toUri(/* flags =*/ 0));
@@ -598,34 +595,9 @@
             XmlSerializer out = new FastXmlSerializer();
             out.setOutput(outs, StandardCharsets.UTF_8.name());
             out.startDocument(null, true);
-            out.startTag(null, TAG_ROOT);
 
-            final ArrayMap<String, PackageShortcuts> packages = getUserShortcutsLocked(userId);
+            getUserShortcutsLocked(userId).saveToXml(out);
 
-            // Body.
-            for (int i = 0; i < packages.size(); i++) {
-                final String packageName = packages.keyAt(i);
-                final PackageShortcuts shortcuts = packages.valueAt(i);
-
-                // TODO Move this to PackageShortcuts.
-
-                out.startTag(null, "package");
-
-                writeAttr(out, "name", packageName);
-                writeAttr(out, "dynamic-count", shortcuts.mDynamicShortcutCount);
-                writeAttr(out, "call-count", shortcuts.mApiCallCountInner);
-                writeAttr(out, "last-reset", shortcuts.mLastResetTime);
-
-                final int size = shortcuts.getShortcuts().size();
-                for (int j = 0; j < size; j++) {
-                    saveShortcut(out, shortcuts.getShortcuts().valueAt(j));
-                }
-
-                out.endTag(null, "package");
-            }
-
-            // Epilogue.
-            out.endTag(null, TAG_ROOT);
             out.endDocument();
 
             // Close.
@@ -636,38 +608,16 @@
         }
     }
 
-    private void saveShortcut(XmlSerializer out, ShortcutInfo si)
-            throws IOException, XmlPullParserException {
-        out.startTag(null, "shortcut");
-        writeAttr(out, "id", si.getId());
-        // writeAttr(out, "package", si.getPackageName()); // not needed
-        writeAttr(out, "activity", si.getActivityComponent());
-        // writeAttr(out, "icon", si.getIcon());  // We don't save it.
-        writeAttr(out, "title", si.getTitle());
-        writeAttr(out, "intent", si.getIntent());
-        writeAttr(out, "weight", si.getWeight());
-        writeAttr(out, "timestamp", si.getLastChangedTimestamp());
-        writeAttr(out, "flags", si.getFlags());
-        writeAttr(out, "icon-res", si.getIconResourceId());
-        writeAttr(out, "bitmap-path", si.getBitmapPath());
-
-        writeTagExtra(out, "intent-extras", si.getIntentPersistableExtras());
-        writeTagExtra(out, "extras", si.getExtras());
-
-        out.endTag(null, "shortcut");
-    }
-
-    private static IOException throwForInvalidTag(int depth, String tag) throws IOException {
+    static IOException throwForInvalidTag(int depth, String tag) throws IOException {
         throw new IOException(String.format("Invalid tag '%s' found at depth %d", tag, depth));
     }
 
     @Nullable
-    private ArrayMap<String, PackageShortcuts> loadUserLocked(@UserIdInt int userId) {
+    private UserShortcuts loadUserLocked(@UserIdInt int userId) {
         final File path = new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
         if (DEBUG) {
             Slog.i(TAG, "Loading from " + path);
         }
-        path.mkdirs();
         final AtomicFile file = new AtomicFile(path);
 
         final FileInputStream in;
@@ -679,14 +629,11 @@
             }
             return null;
         }
-        final ArrayMap<String, PackageShortcuts> ret = new ArrayMap<String, PackageShortcuts>();
+        UserShortcuts ret = null;
         try {
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(in, StandardCharsets.UTF_8.name());
 
-            String packageName = null;
-            PackageShortcuts shortcuts = null;
-
             int type;
             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
                 if (type != XmlPullParser.START_TAG) {
@@ -694,45 +641,14 @@
                 }
                 final int depth = parser.getDepth();
 
-                // TODO Move some of this to PackageShortcuts.
-
                 final String tag = parser.getName();
                 if (DEBUG_LOAD) {
                     Slog.d(TAG, String.format("depth=%d type=%d name=%s",
                             depth, type, tag));
                 }
-                switch (depth) {
-                    case 1: {
-                        if (TAG_ROOT.equals(tag)) {
-                            continue;
-                        }
-                        break;
-                    }
-                    case 2: {
-                        switch (tag) {
-                            case "package":
-                                packageName = parseStringAttribute(parser, "name");
-                                shortcuts = new PackageShortcuts();
-                                ret.put(packageName, shortcuts);
-
-                                shortcuts.mDynamicShortcutCount =
-                                        (int) parseLongAttribute(parser, "dynamic-count");
-                                shortcuts.mApiCallCountInner =
-                                        (int) parseLongAttribute(parser, "call-count");
-                                shortcuts.mLastResetTime = parseLongAttribute(parser, "last-reset");
-                                continue;
-                        }
-                        break;
-                    }
-                    case 3: {
-                        switch (tag) {
-                            case "shortcut":
-                                final ShortcutInfo si = parseShortcut(parser, packageName);
-                                shortcuts.mShortcuts.put(si.getId(), si);
-                                continue;
-                        }
-                        break;
-                    }
+                if ((depth == 1) && TAG_USER.equals(tag)) {
+                    ret = UserShortcuts.loadFromXml(parser, userId);
+                    continue;
                 }
                 throwForInvalidTag(depth, tag);
             }
@@ -745,60 +661,6 @@
         }
     }
 
-    private ShortcutInfo parseShortcut(XmlPullParser parser, String packgeName)
-            throws IOException, XmlPullParserException {
-        String id;
-        ComponentName activityComponent;
-        Icon icon;
-        String title;
-        Intent intent;
-        PersistableBundle intentPersistableExtras = null;
-        int weight;
-        PersistableBundle extras = null;
-        long lastChangedTimestamp;
-        int flags;
-        int iconRes;
-        String bitmapPath;
-
-        id = parseStringAttribute(parser, "id");
-        activityComponent = parseComponentNameAttribute(parser, "activity");
-        title = parseStringAttribute(parser, "title");
-        intent = parseIntentAttribute(parser, "intent");
-        weight = (int) parseLongAttribute(parser, "weight");
-        lastChangedTimestamp = (int) parseLongAttribute(parser, "timestamp");
-        flags = (int) parseLongAttribute(parser, "flags");
-        iconRes = (int) parseLongAttribute(parser, "icon-res");
-        bitmapPath = parseStringAttribute(parser, "bitmap-path");
-
-        final int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type != XmlPullParser.START_TAG) {
-                continue;
-            }
-            final int depth = parser.getDepth();
-            final String tag = parser.getName();
-            if (DEBUG_LOAD) {
-                Slog.d(TAG, String.format("  depth=%d type=%d name=%s",
-                        depth, type, tag));
-            }
-            switch (tag) {
-                case "intent-extras":
-                    intentPersistableExtras = PersistableBundle.restoreFromXml(parser);
-                    continue;
-                case "extras":
-                    extras = PersistableBundle.restoreFromXml(parser);
-                    continue;
-            }
-            throw throwForInvalidTag(depth, tag);
-        }
-        return new ShortcutInfo(
-                id, packgeName, activityComponent, /* icon =*/ null, title, intent,
-                intentPersistableExtras, weight, extras, lastChangedTimestamp, flags,
-                iconRes, bitmapPath);
-    }
-
     // TODO Actually make it async.
     private void scheduleSaveBaseState() {
         synchronized (mLock) {
@@ -807,7 +669,7 @@
     }
 
     // TODO Actually make it async.
-    private void scheduleSaveUser(@UserIdInt int userId) {
+    void scheduleSaveUser(@UserIdInt int userId) {
         synchronized (mLock) {
             saveUserLocked(userId);
         }
@@ -825,6 +687,10 @@
         return mRawLastResetTime + mResetInterval;
     }
 
+    static boolean isClockValid(long time) {
+        return time >= 1420070400; // Thu, 01 Jan 2015 00:00:00 GMT
+    }
+
     /**
      * Update the last reset time.
      */
@@ -839,8 +705,10 @@
             mRawLastResetTime = now;
         } else if (now < mRawLastResetTime) {
             // Clock rewound.
-            // TODO Randomize??
-            mRawLastResetTime = now;
+            if (isClockValid(now)) {
+                // TODO Randomize??
+                mRawLastResetTime = now;
+            }
         } else {
             // TODO Do it properly.
             while ((mRawLastResetTime + mResetInterval) <= now) {
@@ -855,14 +723,14 @@
     /** Return the per-user state. */
     @GuardedBy("mLock")
     @NonNull
-    private ArrayMap<String, PackageShortcuts> getUserShortcutsLocked(@UserIdInt int userId) {
-        ArrayMap<String, PackageShortcuts> userPackages = mShortcuts.get(userId);
+    private UserShortcuts getUserShortcutsLocked(@UserIdInt int userId) {
+        UserShortcuts userPackages = mUsers.get(userId);
         if (userPackages == null) {
             userPackages = loadUserLocked(userId);
             if (userPackages == null) {
-                userPackages = new ArrayMap<>();
+                userPackages = new UserShortcuts(userId);
             }
-            mShortcuts.put(userId, userPackages);
+            mUsers.put(userId, userPackages);
         }
         return userPackages;
     }
@@ -872,17 +740,206 @@
     @NonNull
     private PackageShortcuts getPackageShortcutsLocked(
             @NonNull String packageName, @UserIdInt int userId) {
-        final ArrayMap<String, PackageShortcuts> userPackages = getUserShortcutsLocked(userId);
-        PackageShortcuts shortcuts = userPackages.get(packageName);
+        final UserShortcuts userPackages = getUserShortcutsLocked(userId);
+        PackageShortcuts shortcuts = userPackages.getPackages().get(packageName);
         if (shortcuts == null) {
-            shortcuts = new PackageShortcuts();
-            userPackages.put(packageName, shortcuts);
+            shortcuts = new PackageShortcuts(userId, packageName);
+            userPackages.getPackages().put(packageName, shortcuts);
         }
         return shortcuts;
     }
 
     // === Caller validation ===
 
+    void removeIcon(@UserIdInt int userId, ShortcutInfo shortcut) {
+        if (shortcut.getBitmapPath() != null) {
+            if (DEBUG) {
+                Slog.d(TAG, "Removing " + shortcut.getBitmapPath());
+            }
+            new File(shortcut.getBitmapPath()).delete();
+
+            shortcut.setBitmapPath(null);
+            shortcut.setIconResourceId(0);
+            shortcut.clearFlags(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES);
+        }
+    }
+
+    @VisibleForTesting
+    static class FileOutputStreamWithPath extends FileOutputStream {
+        private final File mFile;
+
+        public FileOutputStreamWithPath(File file) throws FileNotFoundException {
+            super(file);
+            mFile = file;
+        }
+
+        public File getFile() {
+            return mFile;
+        }
+    }
+
+    /**
+     * Build the cached bitmap filename for a shortcut icon.
+     *
+     * The filename will be based on the ID, except certain characters will be escaped.
+     */
+    @VisibleForTesting
+    FileOutputStreamWithPath openIconFileForWrite(@UserIdInt int userId, ShortcutInfo shortcut)
+            throws IOException {
+        final File packagePath = new File(getUserBitmapFilePath(userId),
+                shortcut.getPackageName());
+        if (!packagePath.isDirectory()) {
+            packagePath.mkdirs();
+            if (!packagePath.isDirectory()) {
+                throw new IOException("Unable to create directory " + packagePath);
+            }
+            SELinux.restorecon(packagePath);
+        }
+
+        final String baseName = String.valueOf(injectCurrentTimeMillis());
+        for (int suffix = 0;; suffix++) {
+            final String filename = (suffix == 0 ? baseName : baseName + "_" + suffix) + ".png";
+            final File file = new File(packagePath, filename);
+            if (!file.exists()) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Saving icon to " + file.getAbsolutePath());
+                }
+                return new FileOutputStreamWithPath(file);
+            }
+        }
+    }
+
+    void saveIconAndFixUpShortcut(@UserIdInt int userId, ShortcutInfo shortcut) {
+        if (shortcut.hasIconFile() || shortcut.hasIconResource()) {
+            return;
+        }
+
+        final long token = injectClearCallingIdentity();
+        try {
+            // Clear icon info on the shortcut.
+            shortcut.setIconResourceId(0);
+            shortcut.setBitmapPath(null);
+
+            final Icon icon = shortcut.getIcon();
+            if (icon == null) {
+                return; // has no icon
+            }
+
+            Bitmap bitmap = null;
+            try {
+                switch (icon.getType()) {
+                    case Icon.TYPE_RESOURCE: {
+                        injectValidateIconResPackage(shortcut, icon);
+
+                        shortcut.setIconResourceId(icon.getResId());
+                        shortcut.addFlags(ShortcutInfo.FLAG_HAS_ICON_RES);
+                        return;
+                    }
+                    case Icon.TYPE_BITMAP: {
+                        bitmap = icon.getBitmap();
+                        break;
+                    }
+                    case Icon.TYPE_URI: {
+                        final Uri uri = ContentProvider.maybeAddUserId(icon.getUri(), userId);
+
+                        try (InputStream is = mContext.getContentResolver().openInputStream(uri)) {
+
+                            bitmap = BitmapFactory.decodeStream(is);
+
+                        } catch (IOException e) {
+                            Slog.e(TAG, "Unable to load icon from " + uri);
+                            return;
+                        }
+                        break;
+                    }
+                    default:
+                        // This shouldn't happen because we've already validated the icon, but
+                        // just in case.
+                        throw ShortcutInfo.getInvalidIconException();
+                }
+                if (bitmap == null) {
+                    Slog.e(TAG, "Null bitmap detected");
+                    return;
+                }
+                // Shrink and write to the file.
+                File path = null;
+                try {
+                    final FileOutputStreamWithPath out = openIconFileForWrite(userId, shortcut);
+                    try {
+                        path = out.getFile();
+
+                        shrinkBitmap(bitmap, mMaxIconDimension)
+                                .compress(mIconPersistFormat, mIconPersistQuality, out);
+
+                        shortcut.setBitmapPath(out.getFile().getAbsolutePath());
+                        shortcut.addFlags(ShortcutInfo.FLAG_HAS_ICON_FILE);
+                    } finally {
+                        IoUtils.closeQuietly(out);
+                    }
+                } catch (IOException|RuntimeException e) {
+                    // STOPSHIP Change wtf to e
+                    Slog.wtf(ShortcutService.TAG, "Unable to write bitmap to file", e);
+                    if (path != null && path.exists()) {
+                        path.delete();
+                    }
+                }
+            } finally {
+                if (bitmap != null) {
+                    bitmap.recycle();
+                }
+                // Once saved, we won't use the original icon information, so null it out.
+                shortcut.clearIcon();
+            }
+        } finally {
+            injectRestoreCallingIdentity(token);
+        }
+    }
+
+    // Unfortunately we can't do this check in unit tests because we fake creator package names,
+    // so override in unit tests.
+    // TODO CTS this case.
+    void injectValidateIconResPackage(ShortcutInfo shortcut, Icon icon) {
+        if (!shortcut.getPackageName().equals(icon.getResPackage())) {
+            throw new IllegalArgumentException(
+                    "Icon resource must reside in shortcut owner package");
+        }
+    }
+
+    @VisibleForTesting
+    static Bitmap shrinkBitmap(Bitmap in, int maxSize) {
+        // Original width/height.
+        final int ow = in.getWidth();
+        final int oh = in.getHeight();
+        if ((ow <= maxSize) && (oh <= maxSize)) {
+            if (DEBUG) {
+                Slog.d(TAG, String.format("Icon size %dx%d, no need to shrink", ow, oh));
+            }
+            return in;
+        }
+        final int longerDimension = Math.max(ow, oh);
+
+        // New width and height.
+        final int nw = ow * maxSize / longerDimension;
+        final int nh = oh * maxSize / longerDimension;
+        if (DEBUG) {
+            Slog.d(TAG, String.format("Icon size %dx%d, shrinking to %dx%d",
+                    ow, oh, nw, nh));
+        }
+
+        final Bitmap scaledBitmap = Bitmap.createBitmap(nw, nh, Bitmap.Config.ARGB_8888);
+        final Canvas c = new Canvas(scaledBitmap);
+
+        final RectF dst = new RectF(0, 0, nw, nh);
+
+        c.drawBitmap(in, /*src=*/ null, dst, /* paint =*/ null);
+
+        in.recycle();
+
+        return scaledBitmap;
+    }
+
+    // === Caller validation ===
+
     private boolean isCallerSystem() {
         final int callingUid = injectBinderCallingUid();
          return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID);
@@ -915,36 +972,30 @@
         if (UserHandle.getUserId(callingUid) != userId) {
             throw new SecurityException("Invalid user-ID");
         }
-        verifyCallingPackage(packageName);
-    }
-
-    private void verifyCallingPackage(@NonNull String packageName) {
-        Preconditions.checkStringNotEmpty(packageName, "packageName");
-
-        if (isCallerSystem()) {
-            return; // no check
-        }
-
-        if (injectGetPackageUid(packageName) == injectBinderCallingUid()) {
+        if (injectGetPackageUid(packageName, userId) == injectBinderCallingUid()) {
             return; // Caller is valid.
         }
         throw new SecurityException("Caller UID= doesn't own " + packageName);
     }
 
     // Test overrides it.
-    int injectGetPackageUid(String packageName) {
+    int injectGetPackageUid(@NonNull String packageName, @UserIdInt int userId) {
         try {
 
             // TODO Is MATCH_UNINSTALLED_PACKAGES correct to get SD card app info?
 
-            return mContext.getPackageManager().getPackageUid(packageName,
+            return mContext.getPackageManager().getPackageUidAsUser(packageName,
                     PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
-                            | PackageManager.MATCH_UNINSTALLED_PACKAGES);
+                            | PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
         } catch (NameNotFoundException e) {
             return -1;
         }
     }
 
+    void postToHandler(Runnable r) {
+        mHandler.post(r);
+    }
+
     /**
      * Throw if {@code numShortcuts} is bigger than {@link #mMaxDynamicShortcuts}.
      */
@@ -964,17 +1015,16 @@
     }
 
     private void notifyListeners(@NonNull String packageName, @UserIdInt int userId) {
-        final ArrayList<ShortcutChangeListener> copy;
-        final List<ShortcutInfo> shortcuts = new ArrayList<>();
-        synchronized (mLock) {
-            copy = new ArrayList<>(mListeners);
-
-            getPackageShortcutsLocked(packageName, userId)
-                    .findAll(shortcuts, /* query =*/ null, ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO);
-        }
-        for (int i = copy.size() - 1; i >= 0; i--) {
-            copy.get(i).onShortcutChanged(packageName, shortcuts, userId);
-        }
+        postToHandler(() -> {
+            final ArrayList<ShortcutChangeListener> copy;
+            synchronized (mLock) {
+                copy = new ArrayList<>(mListeners);
+            }
+            // Note onShortcutChanged() needs to be called with the system service permissions.
+            for (int i = copy.size() - 1; i >= 0; i--) {
+                copy.get(i).onShortcutChanged(packageName, userId);
+            }
+        });
     }
 
     /**
@@ -983,8 +1033,10 @@
      * - Make sure the intent's extras are persistable, and them to set
      *  {@link ShortcutInfo#mIntentPersistableExtras}.  Also clear its extras.
      * - Clear flags.
+     *
+     * TODO Detailed unit tests
      */
-    private void fixUpIncomingShortcutInfo(@NonNull ShortcutInfo shortcut) {
+    private void fixUpIncomingShortcutInfo(@NonNull ShortcutInfo shortcut, boolean forUpdate) {
         Preconditions.checkNotNull(shortcut, "Null shortcut detected");
         if (shortcut.getActivityComponent() != null) {
             Preconditions.checkState(
@@ -993,24 +1045,60 @@
                     "Activity package name mismatch");
         }
 
-        shortcut.enforceMandatoryFields();
-
-        final Intent intent = shortcut.getIntent();
-        final Bundle intentExtras = intent.getExtras();
-        if (intentExtras != null && intentExtras.size() > 0) {
-            intent.replaceExtras((Bundle) null);
-
-            // PersistableBundle's constructor will throw IllegalArgumentException if original
-            // extras contain something not persistable.
-            shortcut.setIntentPersistableExtras(new PersistableBundle(intentExtras));
+        if (!forUpdate) {
+            shortcut.enforceMandatoryFields();
+        }
+        if (shortcut.getIcon() != null) {
+            ShortcutInfo.validateIcon(shortcut.getIcon());
         }
 
-        // TODO Save the icon
-        shortcut.setIcon(null);
+        validateForXml(shortcut.getId());
+        validateForXml(shortcut.getTitle());
+        validatePersistableBundleForXml(shortcut.getIntentPersistableExtras());
+        validatePersistableBundleForXml(shortcut.getExtras());
 
         shortcut.setFlags(0);
     }
 
+    // KXmlSerializer is strict and doesn't allow certain characters, so we disallow those
+    // characters.
+
+    private static void validatePersistableBundleForXml(PersistableBundle b) {
+        if (b == null || b.size() == 0) {
+            return;
+        }
+        for (String key : b.keySet()) {
+            validateForXml(key);
+            final Object value = b.get(key);
+            if (value == null) {
+                continue;
+            } else if (value instanceof String) {
+                validateForXml((String) value);
+            } else if (value instanceof String[]) {
+                for (String v : (String[]) value) {
+                    validateForXml(v);
+                }
+            } else if (value instanceof PersistableBundle) {
+                validatePersistableBundleForXml((PersistableBundle) value);
+            }
+        }
+    }
+
+    private static void validateForXml(String s) {
+        if (TextUtils.isEmpty(s)) {
+            return;
+        }
+        for (int i = s.length() - 1; i >= 0; i--) {
+            if (!isAllowedInXml(s.charAt(i))) {
+                throw new IllegalArgumentException("Unsupported character detected in: " + s);
+            }
+        }
+    }
+
+    private static boolean isAllowedInXml(char c) {
+        return (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd);
+    }
+
     // === APIs ===
 
     @Override
@@ -1032,11 +1120,11 @@
 
             // Validate the shortcuts.
             for (int i = 0; i < size; i++) {
-                fixUpIncomingShortcutInfo(newShortcuts.get(i));
+                fixUpIncomingShortcutInfo(newShortcuts.get(i), /* forUpdate= */ false);
             }
 
             // First, remove all un-pinned; dynamic shortcuts
-            ps.deleteAllDynamicShortcuts();
+            ps.deleteAllDynamicShortcuts(this);
 
             // Then, add/update all.  We need to make sure to take over "pinned" flag.
             for (int i = 0; i < size; i++) {
@@ -1046,7 +1134,6 @@
             }
         }
         userPackageChanged(packageName, userId);
-
         return true;
     }
 
@@ -1056,15 +1143,34 @@
         verifyCaller(packageName, userId);
 
         final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
+        final int size = newShortcuts.size();
 
         synchronized (mLock) {
+            final PackageShortcuts ps = getPackageShortcutsLocked(packageName, userId);
 
-            if (true) {
-                throw new RuntimeException("not implemented yet");
+            // Throttling.
+            if (!ps.tryApiCall(this)) {
+                return false;
             }
 
-            // TODO Similar to setDynamicShortcuts, but don't add new ones, and don't change flags.
-            // Update non-null fields only.
+            for (int i = 0; i < size; i++) {
+                final ShortcutInfo source = newShortcuts.get(i);
+                fixUpIncomingShortcutInfo(source, /* forUpdate= */ true);
+
+                final ShortcutInfo target = ps.findShortcutById(source.getId());
+                if (target != null) {
+                    final boolean replacingIcon = (source.getIcon() != null);
+                    if (replacingIcon) {
+                        removeIcon(userId, target);
+                    }
+
+                    target.copyNonNullFieldsFrom(source);
+
+                    if (replacingIcon) {
+                        saveIconAndFixUpShortcut(userId, target);
+                    }
+                }
+            }
         }
         userPackageChanged(packageName, userId);
 
@@ -1085,7 +1191,7 @@
             }
 
             // Validate the shortcut.
-            fixUpIncomingShortcutInfo(newShortcut);
+            fixUpIncomingShortcutInfo(newShortcut, /* forUpdate= */ false);
 
             // Add it.
             newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
@@ -1103,7 +1209,7 @@
         Preconditions.checkStringNotEmpty(shortcutId, "shortcutId must be provided");
 
         synchronized (mLock) {
-            getPackageShortcutsLocked(packageName, userId).deleteDynamicWithId(shortcutId);
+            getPackageShortcutsLocked(packageName, userId).deleteDynamicWithId(this, shortcutId);
         }
         userPackageChanged(packageName, userId);
     }
@@ -1113,7 +1219,7 @@
         verifyCaller(packageName, userId);
 
         synchronized (mLock) {
-            getPackageShortcutsLocked(packageName, userId).deleteAllDynamicShortcuts();
+            getPackageShortcutsLocked(packageName, userId).deleteAllDynamicShortcuts(this);
         }
         userPackageChanged(packageName, userId);
     }
@@ -1177,6 +1283,13 @@
         }
     }
 
+    @Override
+    public int getIconMaxDimensions(String packageName, int userId) throws RemoteException {
+        synchronized (mLock) {
+            return mMaxIconDimension;
+        }
+    }
+
     /**
      * Reset all throttling, for developer options and command line.  Only system/shell can call it.
      */
@@ -1184,15 +1297,96 @@
     public void resetThrottling() {
         enforceSystemOrShell();
 
-        resetThrottlingInner();
+        resetThrottlingInner(getCallingUserId());
     }
 
-    @VisibleForTesting
-    void resetThrottlingInner() {
+    void resetThrottlingInner(@UserIdInt int userId) {
         synchronized (mLock) {
-            mRawLastResetTime = injectCurrentTimeMillis();
+            getUserShortcutsLocked(userId).resetThrottling();
         }
-        scheduleSaveBaseState();
+        scheduleSaveUser(userId);
+        Slog.i(TAG, "ShortcutManager: throttling counter reset");
+    }
+
+    // We override this method in unit tests to do a simpler check.
+    boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
+        return hasShortcutHostPermissionInner(callingPackage, userId);
+    }
+
+    // This method is extracted so we can directly call this method from unit tests,
+    // even when hasShortcutPermission() is overridden.
+    @VisibleForTesting
+    boolean hasShortcutHostPermissionInner(@NonNull String callingPackage, int userId) {
+        synchronized (mLock) {
+            long start = 0;
+            if (DEBUG) {
+                start = System.currentTimeMillis();
+            }
+
+            final UserShortcuts user = getUserShortcutsLocked(userId);
+
+            final List<ResolveInfo> allHomeCandidates = new ArrayList<>();
+
+            // Default launcher from package manager.
+            final ComponentName defaultLauncher = injectPackageManagerInternal()
+                    .getHomeActivitiesAsUser(allHomeCandidates, userId);
+
+            ComponentName detected;
+            if (defaultLauncher != null) {
+                detected = defaultLauncher;
+                if (DEBUG) {
+                    Slog.v(TAG, "Default launcher from PM: " + detected);
+                }
+            } else {
+                detected = user.getLauncherComponent();
+
+                // TODO: Make sure it's still enabled.
+                if (DEBUG) {
+                    Slog.v(TAG, "Cached launcher: " + detected);
+                }
+            }
+
+            if (detected == null) {
+                // If we reach here, that means it's the first check since the user was created,
+                // and there's already multiple launchers and there's no default set.
+                // Find the system one with the highest priority.
+                // (We need to check the priority too because of FallbackHome in Settings.)
+                // If there's no system launcher yet, then no one can access shortcuts, until
+                // the user explicitly
+                final int size = allHomeCandidates.size();
+
+                int lastPriority = Integer.MIN_VALUE;
+                for (int i = 0; i < size; i++) {
+                    final ResolveInfo ri = allHomeCandidates.get(i);
+                    if (!ri.activityInfo.applicationInfo.isSystemApp()) {
+                        continue;
+                    }
+                    if (DEBUG) {
+                        Slog.d(TAG, String.format("hasShortcutPermissionInner: pkg=%s prio=%d",
+                                ri.activityInfo.getComponentName(), ri.priority));
+                    }
+                    if (ri.priority < lastPriority) {
+                        continue;
+                    }
+                    detected = ri.activityInfo.getComponentName();
+                    lastPriority = ri.priority;
+                }
+            }
+            if (DEBUG) {
+                long end = System.currentTimeMillis();
+                Slog.v(TAG, String.format("hasShortcutPermission took %d ms", end - start));
+            }
+            if (detected != null) {
+                if (DEBUG) {
+                    Slog.v(TAG, "Detected launcher: " + detected);
+                }
+                user.setLauncherComponent(this, detected);
+                return detected.getPackageName().equals(callingPackage);
+            } else {
+                // Default launcher not found.
+                return false;
+            }
+        }
     }
 
     /**
@@ -1216,8 +1410,8 @@
                             userId, ret, cloneFlag);
                 } else {
                     final ArrayMap<String, PackageShortcuts> packages =
-                            getUserShortcutsLocked(userId);
-                    for (int i = 0; i < packages.size(); i++) {
+                            getUserShortcutsLocked(userId).getPackages();
+                    for (int i = packages.size() - 1; i >= 0; i--) {
                         getShortcutsInnerLocked(
                                 packages.keyAt(i),
                                 changedSince, componentName, queryFlags, userId, ret, cloneFlag);
@@ -1274,7 +1468,8 @@
             Preconditions.checkNotNull(shortcutIds, "shortcutIds");
 
             synchronized (mLock) {
-                getPackageShortcutsLocked(packageName, userId).pinAll(shortcutIds);
+                getPackageShortcutsLocked(packageName, userId).replacePinned(
+                        ShortcutService.this, callingPackage, shortcutIds);
             }
             userPackageChanged(packageName, userId);
         }
@@ -1289,18 +1484,8 @@
             synchronized (mLock) {
                 final ShortcutInfo fullShortcut =
                         getPackageShortcutsLocked(packageName, userId)
-                        .getShortcuts().get(shortcutId);
-                if (fullShortcut == null) {
-                    return null;
-                } else {
-                    final Intent intent = fullShortcut.getIntent();
-                    final PersistableBundle extras = fullShortcut.getIntentPersistableExtras();
-                    if (extras != null) {
-                        intent.replaceExtras(new Bundle(extras));
-                    }
-
-                    return intent;
-                }
+                        .findShortcutById(shortcutId);
+                return fullShortcut == null ? null : fullShortcut.getIntent();
             }
         }
 
@@ -1310,6 +1495,50 @@
                 mListeners.add(Preconditions.checkNotNull(listener));
             }
         }
+
+        @Override
+        public int getShortcutIconResId(@NonNull String callingPackage,
+                @NonNull ShortcutInfo shortcut, int userId) {
+            Preconditions.checkNotNull(shortcut, "shortcut");
+
+            synchronized (mLock) {
+                final ShortcutInfo shortcutInfo = getPackageShortcutsLocked(
+                        shortcut.getPackageName(), userId).findShortcutById(shortcut.getId());
+                return (shortcutInfo != null && shortcutInfo.hasIconResource())
+                        ? shortcutInfo.getIconResourceId() : 0;
+            }
+        }
+
+        @Override
+        public ParcelFileDescriptor getShortcutIconFd(@NonNull String callingPackage,
+                @NonNull ShortcutInfo shortcutIn, int userId) {
+            Preconditions.checkNotNull(shortcutIn, "shortcut");
+
+            synchronized (mLock) {
+                final ShortcutInfo shortcutInfo = getPackageShortcutsLocked(
+                        shortcutIn.getPackageName(), userId).findShortcutById(shortcutIn.getId());
+                if (shortcutInfo == null || !shortcutInfo.hasIconFile()) {
+                    return null;
+                }
+                try {
+                    if (shortcutInfo.getBitmapPath() == null) {
+                        Slog.w(TAG, "null bitmap detected in getShortcutIconFd()");
+                        return null;
+                    }
+                    return ParcelFileDescriptor.open(
+                            new File(shortcutInfo.getBitmapPath()),
+                            ParcelFileDescriptor.MODE_READ_ONLY);
+                } catch (FileNotFoundException e) {
+                    Slog.e(TAG, "Icon file not found: " + shortcutInfo.getBitmapPath());
+                    return null;
+                }
+            }
+        }
+
+        @Override
+        public boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
+            return ShortcutService.this.hasShortcutHostPermission(callingPackage, userId);
+        }
     }
 
     // === Dump ===
@@ -1336,78 +1565,42 @@
             pw.print(now);
             pw.print("] ");
             pw.print(formatTime(now));
+
             pw.print("  Raw last reset: [");
             pw.print(mRawLastResetTime);
             pw.print("] ");
             pw.print(formatTime(mRawLastResetTime));
 
             final long last = getLastResetTimeLocked();
-            final long next = getNextResetTimeLocked();
             pw.print("  Last reset: [");
             pw.print(last);
             pw.print("] ");
             pw.print(formatTime(last));
 
+            final long next = getNextResetTimeLocked();
             pw.print("  Next reset: [");
             pw.print(next);
             pw.print("] ");
             pw.print(formatTime(next));
             pw.println();
 
+            pw.print("  Max icon dim: ");
+            pw.print(mMaxIconDimension);
+            pw.print("  Icon format: ");
+            pw.print(mIconPersistFormat);
+            pw.print("  Icon quality: ");
+            pw.print(mIconPersistQuality);
             pw.println();
 
-            for (int i = 0; i < mShortcuts.size(); i++) {
-                dumpUserLocked(pw, mShortcuts.keyAt(i));
+
+            for (int i = 0; i < mUsers.size(); i++) {
+                pw.println();
+                mUsers.valueAt(i).dump(this, pw, "  ");
             }
-
         }
     }
 
-    private void dumpUserLocked(PrintWriter pw, int userId) {
-        pw.print("  User: ");
-        pw.print(userId);
-        pw.println();
-
-        final ArrayMap<String, PackageShortcuts> packages = mShortcuts.get(userId);
-        if (packages == null) {
-            return;
-        }
-        for (int j = 0; j < packages.size(); j++) {
-            dumpPackageLocked(pw, userId, packages.keyAt(j));
-        }
-        pw.println();
-    }
-
-    private void dumpPackageLocked(PrintWriter pw, int userId, String packageName) {
-        final PackageShortcuts shortcuts = mShortcuts.get(userId).get(packageName);
-        if (shortcuts == null) {
-            return;
-        }
-
-        pw.print("    Package: ");
-        pw.print(packageName);
-        pw.println();
-
-        pw.print("      Calls: ");
-        pw.print(shortcuts.getApiCallCount(this));
-        pw.println();
-
-        // This should be after getApiCallCount(), which may update it.
-        pw.print("      Last reset: [");
-        pw.print(shortcuts.mLastResetTime);
-        pw.print("] ");
-        pw.print(formatTime(shortcuts.mLastResetTime));
-        pw.println();
-
-        pw.println("      Shortcuts:");
-        final int size = shortcuts.getShortcuts().size();
-        for (int i = 0; i < size; i++) {
-            pw.print("        ");
-            pw.println(shortcuts.getShortcuts().valueAt(i).toInsecureString());
-        }
-    }
-
-    private static String formatTime(long time) {
+    static String formatTime(long time) {
         Time tobj = new Time();
         tobj.set(time);
         return tobj.format("%Y-%m-%d %H:%M:%S");
@@ -1424,24 +1617,74 @@
         (new MyShellCommand()).exec(this, in, out, err, args, resultReceiver);
     }
 
+    static class CommandException extends Exception {
+        public CommandException(String message) {
+            super(message);
+        }
+    }
+
     /**
      * Handle "adb shell cmd".
      */
     private class MyShellCommand extends ShellCommand {
+
+        private int mUserId = UserHandle.USER_SYSTEM;
+
+        private void parseOptions(boolean takeUser)
+                throws CommandException {
+            String opt;
+            while ((opt = getNextOption()) != null) {
+                switch (opt) {
+                    case "--user":
+                        if (takeUser) {
+                            mUserId = UserHandle.parseUserArg(getNextArgRequired());
+                            break;
+                        }
+                        // fallthrough
+                    default:
+                        throw new CommandException("Unknown option: " + opt);
+                }
+            }
+        }
+
         @Override
         public int onCommand(String cmd) {
             if (cmd == null) {
                 return handleDefaultCommands(cmd);
             }
             final PrintWriter pw = getOutPrintWriter();
-            switch(cmd) {
-                case "reset-package-throttling":
-                    return handleResetPackageThrottling();
-                case "reset-throttling":
-                    return handleResetThrottling();
-                default:
-                    return handleDefaultCommands(cmd);
+            try {
+                switch (cmd) {
+                    case "reset-package-throttling":
+                        handleResetPackageThrottling();
+                        break;
+                    case "reset-throttling":
+                        handleResetThrottling();
+                        break;
+                    case "override-config":
+                        handleOverrideConfig();
+                        break;
+                    case "reset-config":
+                        handleResetConfig();
+                        break;
+                    case "clear-default-launcher":
+                        handleClearDefaultLauncher();
+                        break;
+                    case "get-default-launcher":
+                        handleGetDefaultLauncher();
+                        break;
+                    case "refresh-default-launcher":
+                        handleRefreshDefaultLauncher();
+                        break;
+                    default:
+                        return handleDefaultCommands(cmd);
+                }
+            } catch (CommandException e) {
+                pw.println("Error: " + e.getMessage());
+                return 1;
             }
+            pw.println("Success");
+            return 0;
         }
 
         @Override
@@ -1455,36 +1698,91 @@
             pw.println("cmd shortcut reset-throttling");
             pw.println("    Reset throttling for all packages and users");
             pw.println();
+            pw.println("cmd shortcut override-config CONFIG");
+            pw.println("    Override the configuration for testing (will last until reboot)");
+            pw.println();
+            pw.println("cmd shortcut reset-config");
+            pw.println("    Reset the configuration set with \"update-config\"");
+            pw.println();
+            pw.println("cmd shortcut clear-default-launcher [--user USER_ID]");
+            pw.println("    Clear the cached default launcher");
+            pw.println();
+            pw.println("cmd shortcut get-default-launcher [--user USER_ID]");
+            pw.println("    Show the cached default launcher");
+            pw.println();
+            pw.println("cmd shortcut refresh-default-launcher [--user USER_ID]");
+            pw.println("    Refresh the cached default launcher");
+            pw.println();
         }
 
-        private int handleResetThrottling() {
-            resetThrottling();
+        private int handleResetThrottling() throws CommandException {
+            parseOptions(/* takeUser =*/ true);
+
+            resetThrottlingInner(mUserId);
             return 0;
         }
 
-        private int handleResetPackageThrottling() {
-            final PrintWriter pw = getOutPrintWriter();
+        private void handleResetPackageThrottling() throws CommandException {
+            parseOptions(/* takeUser =*/ true);
 
-            int userId = UserHandle.USER_SYSTEM;
-            String opt;
-            while ((opt = getNextOption()) != null) {
-                switch (opt) {
-                    case "--user":
-                        userId = UserHandle.parseUserArg(getNextArgRequired());
-                        break;
-                    default:
-                        pw.println("Error: Unknown option: " + opt);
-                        return 1;
-                }
-            }
             final String packageName = getNextArgRequired();
 
             synchronized (mLock) {
-                getPackageShortcutsLocked(packageName, userId).resetRateLimitingForCommandLine();
-                saveUserLocked(userId);
+                getPackageShortcutsLocked(packageName, mUserId).resetRateLimitingForCommandLine();
+                saveUserLocked(mUserId);
             }
+        }
 
-            return 0;
+        private void handleOverrideConfig() throws CommandException {
+            final String config = getNextArgRequired();
+
+            synchronized (mLock) {
+                if (!updateConfigurationLocked(config)) {
+                    throw new CommandException("override-config failed.  See logcat for details.");
+                }
+            }
+        }
+
+        private void handleResetConfig() {
+            synchronized (mLock) {
+                loadConfigurationLocked();
+            }
+        }
+
+        private void clearLauncher() {
+            synchronized (mLock) {
+                getUserShortcutsLocked(mUserId).setLauncherComponent(
+                        ShortcutService.this, null);
+            }
+        }
+
+        private void showLauncher() {
+            synchronized (mLock) {
+                // This ensures to set the cached launcher.  Package name doesn't matter.
+                hasShortcutHostPermissionInner("-", mUserId);
+
+                getOutPrintWriter().println("Launcher: "
+                        + getUserShortcutsLocked(mUserId).getLauncherComponent());
+            }
+        }
+
+        private void handleClearDefaultLauncher() throws CommandException {
+            parseOptions(/* takeUser =*/ true);
+
+            clearLauncher();
+        }
+
+        private void handleGetDefaultLauncher() throws CommandException {
+            parseOptions(/* takeUser =*/ true);
+
+            showLauncher();
+        }
+
+        private void handleRefreshDefaultLauncher() throws CommandException {
+            parseOptions(/* takeUser =*/ true);
+
+            clearLauncher();
+            showLauncher();
         }
     }
 
@@ -1500,31 +1798,571 @@
         return getCallingUid();
     }
 
+    final int getCallingUserId() {
+        return UserHandle.getUserId(injectBinderCallingUid());
+    }
+
+    // Injection point.
+    long injectClearCallingIdentity() {
+        return Binder.clearCallingIdentity();
+    }
+
+    // Injection point.
+    void injectRestoreCallingIdentity(long token) {
+        Binder.restoreCallingIdentity(token);
+    }
+
     File injectSystemDataPath() {
         return Environment.getDataSystemDirectory();
     }
 
     File injectUserDataPath(@UserIdInt int userId) {
-        return new File(Environment.getDataSystemDeDirectory(userId), DIRECTORY_PER_USER);
+        return new File(Environment.getDataSystemCeDirectory(userId), DIRECTORY_PER_USER);
     }
 
     @VisibleForTesting
-    SparseArray<ArrayMap<String, PackageShortcuts>> getShortcutsForTest() {
-        return mShortcuts;
+    boolean injectIsLowRamDevice() {
+        return ActivityManager.isLowRamDeviceStatic();
+    }
+
+    PackageManagerInternal injectPackageManagerInternal() {
+        return mPackageManagerInternal;
+    }
+
+    File getUserBitmapFilePath(@UserIdInt int userId) {
+        return new File(injectUserDataPath(userId), DIRECTORY_BITMAPS);
     }
 
     @VisibleForTesting
-    void setMaxDynamicShortcutsForTest(int max) {
-        mMaxDynamicShortcuts = max;
+    SparseArray<UserShortcuts> getShortcutsForTest() {
+        return mUsers;
     }
 
     @VisibleForTesting
-    void setMaxDailyUpdatesForTest(int max) {
-        mMaxDailyUpdates = max;
+    int getMaxDynamicShortcutsForTest() {
+        return mMaxDynamicShortcuts;
     }
 
     @VisibleForTesting
-    public void setResetIntervalForTest(long interval) {
-        mResetInterval = interval;
+    int getMaxDailyUpdatesForTest() {
+        return mMaxDailyUpdates;
+    }
+
+    @VisibleForTesting
+    long getResetIntervalForTest() {
+        return mResetInterval;
+    }
+
+    @VisibleForTesting
+    int getMaxIconDimensionForTest() {
+        return mMaxIconDimension;
+    }
+
+    @VisibleForTesting
+    CompressFormat getIconPersistFormatForTest() {
+        return mIconPersistFormat;
+    }
+
+    @VisibleForTesting
+    int getIconPersistQualityForTest() {
+        return mIconPersistQuality;
+    }
+
+    @VisibleForTesting
+    ShortcutInfo getPackageShortcutForTest(String packageName, String shortcutId, int userId) {
+        synchronized (mLock) {
+            return getPackageShortcutsLocked(packageName, userId).findShortcutById(shortcutId);
+        }
+    }
+}
+
+/**
+ * Per-user information.
+ */
+class UserShortcuts {
+    private static final String TAG = ShortcutService.TAG;
+
+    @UserIdInt
+    final int mUserId;
+
+    private final ArrayMap<String, PackageShortcuts> mPackages = new ArrayMap<>();
+
+    private ComponentName mLauncherComponent;
+
+    public UserShortcuts(int userId) {
+        mUserId = userId;
+    }
+
+    public ArrayMap<String, PackageShortcuts> getPackages() {
+        return mPackages;
+    }
+
+    public void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
+        out.startTag(null, ShortcutService.TAG_USER);
+
+        ShortcutService.writeTagValue(out, ShortcutService.TAG_LAUNCHER,
+                mLauncherComponent);
+
+        for (int i = 0; i < mPackages.size(); i++) {
+            mPackages.valueAt(i).saveToXml(out);
+        }
+
+        out.endTag(null, ShortcutService.TAG_USER);
+    }
+
+    public static UserShortcuts loadFromXml(XmlPullParser parser, int userId)
+            throws IOException, XmlPullParserException {
+        final UserShortcuts ret = new UserShortcuts(userId);
+
+        final int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+            final int depth = parser.getDepth();
+            final String tag = parser.getName();
+            switch (tag) {
+                case ShortcutService.TAG_LAUNCHER:
+                    ret.mLauncherComponent = ShortcutService.parseComponentNameAttribute(
+                            parser, ShortcutService.ATTR_VALUE);
+                    continue;
+                case ShortcutService.TAG_PACKAGE:
+                    final PackageShortcuts shortcuts = PackageShortcuts.loadFromXml(parser, userId);
+
+                    // Don't use addShortcut(), we don't need to save the icon.
+                    ret.getPackages().put(shortcuts.mPackageName, shortcuts);
+                    continue;
+            }
+            throw ShortcutService.throwForInvalidTag(depth, tag);
+        }
+        return ret;
+    }
+
+    public ComponentName getLauncherComponent() {
+        return mLauncherComponent;
+    }
+
+    public void setLauncherComponent(ShortcutService s, ComponentName launcherComponent) {
+        if (Objects.equal(mLauncherComponent, launcherComponent)) {
+            return;
+        }
+        mLauncherComponent = launcherComponent;
+        s.scheduleSaveUser(mUserId);
+    }
+
+    public void resetThrottling() {
+        for (int i = mPackages.size() - 1; i >= 0; i--) {
+            mPackages.valueAt(i).resetThrottling();
+        }
+    }
+
+    public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
+        pw.print(prefix);
+        pw.print("User: ");
+        pw.print(mUserId);
+        pw.println();
+
+        pw.print(prefix);
+        pw.print("  ");
+        pw.print("Default launcher: ");
+        pw.print(mLauncherComponent);
+        pw.println();
+
+        for (int i = 0; i < mPackages.size(); i++) {
+            mPackages.valueAt(i).dump(s, pw, prefix + "  ");
+        }
+    }
+}
+
+/**
+ * All the information relevant to shortcuts from a single package (per-user).
+ */
+class PackageShortcuts {
+    private static final String TAG = ShortcutService.TAG;
+
+    @UserIdInt
+    final int mUserId;
+
+    @NonNull
+    final String mPackageName;
+
+    /**
+     * All the shortcuts from the package, keyed on IDs.
+     */
+    final private ArrayMap<String, ShortcutInfo> mShortcuts = new ArrayMap<>();
+
+    /**
+     * # of dynamic shortcuts.
+     */
+    private int mDynamicShortcutCount = 0;
+
+    /**
+     * # of times the package has called rate-limited APIs.
+     */
+    private int mApiCallCount;
+
+    /**
+     * When {@link #mApiCallCount} was reset last time.
+     */
+    private long mLastResetTime;
+
+    PackageShortcuts(int userId, String packageName) {
+        mUserId = userId;
+        mPackageName = packageName;
+    }
+
+    @Nullable
+    public ShortcutInfo findShortcutById(String id) {
+        return mShortcuts.get(id);
+    }
+
+    private ShortcutInfo deleteShortcut(@NonNull ShortcutService s,
+            @NonNull String id) {
+        final ShortcutInfo shortcut = mShortcuts.remove(id);
+        if (shortcut != null) {
+            s.removeIcon(mUserId, shortcut);
+            shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED);
+        }
+        return shortcut;
+    }
+
+    void addShortcut(@NonNull ShortcutService s, @NonNull ShortcutInfo newShortcut) {
+        deleteShortcut(s, newShortcut.getId());
+        s.saveIconAndFixUpShortcut(mUserId, newShortcut);
+        mShortcuts.put(newShortcut.getId(), newShortcut);
+    }
+
+    /**
+     * Add a shortcut, or update one with the same ID, with taking over existing flags.
+     *
+     * It checks the max number of dynamic shortcuts.
+     */
+    public void updateShortcutWithCapping(@NonNull ShortcutService s,
+            @NonNull ShortcutInfo newShortcut) {
+        final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
+
+        int oldFlags = 0;
+        int newDynamicCount = mDynamicShortcutCount;
+
+        if (oldShortcut != null) {
+            oldFlags = oldShortcut.getFlags();
+            if (oldShortcut.isDynamic()) {
+                newDynamicCount--;
+            }
+        }
+        if (newShortcut.isDynamic()) {
+            newDynamicCount++;
+        }
+        // Make sure there's still room.
+        s.enforceMaxDynamicShortcuts(newDynamicCount);
+
+        // Okay, make it dynamic and add.
+        newShortcut.addFlags(oldFlags);
+
+        addShortcut(s, newShortcut);
+        mDynamicShortcutCount = newDynamicCount;
+    }
+
+    /**
+     * Remove all shortcuts that aren't pinned nor dynamic.
+     */
+    private void removeOrphans(@NonNull ShortcutService s) {
+        ArrayList<String> removeList = null; // Lazily initialize.
+
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
+
+            if (si.isPinned() || si.isDynamic()) continue;
+
+            if (removeList == null) {
+                removeList = new ArrayList<>();
+            }
+            removeList.add(si.getId());
+        }
+        if (removeList != null) {
+            for (int i = removeList.size() - 1 ; i >= 0; i--) {
+                deleteShortcut(s, removeList.get(i));
+            }
+        }
+    }
+
+    public void deleteAllDynamicShortcuts(@NonNull ShortcutService s) {
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_DYNAMIC);
+        }
+        removeOrphans(s);
+        mDynamicShortcutCount = 0;
+    }
+
+    public void deleteDynamicWithId(@NonNull ShortcutService s, @NonNull String shortcutId) {
+        final ShortcutInfo oldShortcut = mShortcuts.get(shortcutId);
+
+        if (oldShortcut == null) {
+            return;
+        }
+        if (oldShortcut.isDynamic()) {
+            mDynamicShortcutCount--;
+        }
+        if (oldShortcut.isPinned()) {
+            oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
+        } else {
+            deleteShortcut(s, shortcutId);
+        }
+    }
+
+    public void replacePinned(@NonNull ShortcutService s, String launcherPackage,
+            List<String> shortcutIds) {
+
+        // TODO Should be per launcherPackage.
+
+        // First, un-pin all shortcuts
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_PINNED);
+        }
+
+        // Then pin ALL
+        for (int i = shortcutIds.size() - 1; i >= 0; i--) {
+            final ShortcutInfo shortcut = mShortcuts.get(shortcutIds.get(i));
+            if (shortcut != null) {
+                shortcut.addFlags(ShortcutInfo.FLAG_PINNED);
+            }
+        }
+
+        removeOrphans(s);
+    }
+
+    /**
+     * Number of calls that the caller has made, since the last reset.
+     */
+    public int getApiCallCount(@NonNull ShortcutService s) {
+        final long last = s.getLastResetTimeLocked();
+
+        final long now = s.injectCurrentTimeMillis();
+        if (ShortcutService.isClockValid(now) && mLastResetTime > now) {
+            // Clock rewound. // TODO Test it
+            mLastResetTime = now;
+        }
+
+        // If not reset yet, then reset.
+        if (mLastResetTime < last) {
+            mApiCallCount = 0;
+            mLastResetTime = last;
+        }
+        return mApiCallCount;
+    }
+
+    /**
+     * If the caller app hasn't been throttled yet, increment {@link #mApiCallCount}
+     * and return true.  Otherwise just return false.
+     */
+    public boolean tryApiCall(@NonNull ShortcutService s) {
+        if (getApiCallCount(s) >= s.mMaxDailyUpdates) {
+            return false;
+        }
+        mApiCallCount++;
+        return true;
+    }
+
+    public void resetRateLimitingForCommandLine() {
+        mApiCallCount = 0;
+        mLastResetTime = 0;
+    }
+
+    /**
+     * Find all shortcuts that match {@code query}.
+     */
+    public void findAll(@NonNull List<ShortcutInfo> result,
+            @Nullable Predicate<ShortcutInfo> query, int cloneFlag) {
+        for (int i = 0; i < mShortcuts.size(); i++) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
+            if (query == null || query.test(si)) {
+                result.add(si.clone(cloneFlag));
+            }
+        }
+    }
+
+    public void resetThrottling() {
+        mApiCallCount = 0;
+    }
+
+    public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
+        pw.print(prefix);
+        pw.print("Package: ");
+        pw.print(mPackageName);
+        pw.println();
+
+        pw.print(prefix);
+        pw.print("  ");
+        pw.print("Calls: ");
+        pw.print(getApiCallCount(s));
+        pw.println();
+
+        // This should be after getApiCallCount(), which may update it.
+        pw.print(prefix);
+        pw.print("  ");
+        pw.print("Last reset: [");
+        pw.print(mLastResetTime);
+        pw.print("] ");
+        pw.print(s.formatTime(mLastResetTime));
+        pw.println();
+
+        pw.println("      Shortcuts:");
+        long totalBitmapSize = 0;
+        final ArrayMap<String, ShortcutInfo> shortcuts = mShortcuts;
+        final int size = shortcuts.size();
+        for (int i = 0; i < size; i++) {
+            final ShortcutInfo si = shortcuts.valueAt(i);
+            pw.print("        ");
+            pw.println(si.toInsecureString());
+            if (si.getBitmapPath() != null) {
+                final long len = new File(si.getBitmapPath()).length();
+                pw.print("          ");
+                pw.print("bitmap size=");
+                pw.println(len);
+
+                totalBitmapSize += len;
+            }
+        }
+        pw.print(prefix);
+        pw.print("  ");
+        pw.print("Total bitmap size: ");
+        pw.print(totalBitmapSize);
+        pw.print(" (");
+        pw.print(Formatter.formatFileSize(s.mContext, totalBitmapSize));
+        pw.println(")");
+    }
+
+    public void saveToXml(@NonNull XmlSerializer out) throws IOException, XmlPullParserException {
+        out.startTag(null, ShortcutService.TAG_PACKAGE);
+
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_NAME, mPackageName);
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_DYNAMIC_COUNT, mDynamicShortcutCount);
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_CALL_COUNT, mApiCallCount);
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_LAST_RESET, mLastResetTime);
+
+        final int size = mShortcuts.size();
+        for (int j = 0; j < size; j++) {
+            saveShortcut(out, mShortcuts.valueAt(j));
+        }
+
+        out.endTag(null, ShortcutService.TAG_PACKAGE);
+    }
+
+    private static void saveShortcut(XmlSerializer out, ShortcutInfo si)
+            throws IOException, XmlPullParserException {
+        out.startTag(null, ShortcutService.TAG_SHORTCUT);
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_ID, si.getId());
+        // writeAttr(out, "package", si.getPackageName()); // not needed
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_ACTIVITY, si.getActivityComponent());
+        // writeAttr(out, "icon", si.getIcon());  // We don't save it.
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_TITLE, si.getTitle());
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_INTENT, si.getIntentNoExtras());
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_WEIGHT, si.getWeight());
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_TIMESTAMP,
+                si.getLastChangedTimestamp());
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_FLAGS, si.getFlags());
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_ICON_RES, si.getIconResourceId());
+        ShortcutService.writeAttr(out, ShortcutService.ATTR_BITMAP_PATH, si.getBitmapPath());
+
+        ShortcutService.writeTagExtra(out, ShortcutService.TAG_INTENT_EXTRAS,
+                si.getIntentPersistableExtras());
+        ShortcutService.writeTagExtra(out, ShortcutService.TAG_EXTRAS, si.getExtras());
+
+        out.endTag(null, ShortcutService.TAG_SHORTCUT);
+    }
+
+    public static PackageShortcuts loadFromXml(XmlPullParser parser, int userId)
+            throws IOException, XmlPullParserException {
+
+        final String packageName = ShortcutService.parseStringAttribute(parser,
+                ShortcutService.ATTR_NAME);
+
+        final PackageShortcuts ret = new PackageShortcuts(userId, packageName);
+
+        ret.mDynamicShortcutCount =
+                ShortcutService.parseIntAttribute(parser, ShortcutService.ATTR_DYNAMIC_COUNT);
+        ret.mApiCallCount =
+                ShortcutService.parseIntAttribute(parser, ShortcutService.ATTR_CALL_COUNT);
+        ret.mLastResetTime =
+                ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_LAST_RESET);
+
+        final int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+            final int depth = parser.getDepth();
+            final String tag = parser.getName();
+            switch (tag) {
+                case ShortcutService.TAG_SHORTCUT:
+                    final ShortcutInfo si = parseShortcut(parser, packageName);
+
+                    // Don't use addShortcut(), we don't need to save the icon.
+                    ret.mShortcuts.put(si.getId(), si);
+                    continue;
+            }
+            throw ShortcutService.throwForInvalidTag(depth, tag);
+        }
+        return ret;
+    }
+
+    private static ShortcutInfo parseShortcut(XmlPullParser parser, String packageName)
+            throws IOException, XmlPullParserException {
+        String id;
+        ComponentName activityComponent;
+        // Icon icon;
+        String title;
+        Intent intent;
+        PersistableBundle intentPersistableExtras = null;
+        int weight;
+        PersistableBundle extras = null;
+        long lastChangedTimestamp;
+        int flags;
+        int iconRes;
+        String bitmapPath;
+
+        id = ShortcutService.parseStringAttribute(parser, ShortcutService.ATTR_ID);
+        activityComponent = ShortcutService.parseComponentNameAttribute(parser,
+                ShortcutService.ATTR_ACTIVITY);
+        title = ShortcutService.parseStringAttribute(parser, ShortcutService.ATTR_TITLE);
+        intent = ShortcutService.parseIntentAttribute(parser, ShortcutService.ATTR_INTENT);
+        weight = (int) ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_WEIGHT);
+        lastChangedTimestamp = (int) ShortcutService.parseLongAttribute(parser,
+                ShortcutService.ATTR_TIMESTAMP);
+        flags = (int) ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_FLAGS);
+        iconRes = (int) ShortcutService.parseLongAttribute(parser, ShortcutService.ATTR_ICON_RES);
+        bitmapPath = ShortcutService.parseStringAttribute(parser, ShortcutService.ATTR_BITMAP_PATH);
+
+        final int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+            final int depth = parser.getDepth();
+            final String tag = parser.getName();
+            if (ShortcutService.DEBUG_LOAD) {
+                Slog.d(TAG, String.format("  depth=%d type=%d name=%s",
+                        depth, type, tag));
+            }
+            switch (tag) {
+                case ShortcutService.TAG_INTENT_EXTRAS:
+                    intentPersistableExtras = PersistableBundle.restoreFromXml(parser);
+                    continue;
+                case ShortcutService.TAG_EXTRAS:
+                    extras = PersistableBundle.restoreFromXml(parser);
+                    continue;
+            }
+            throw ShortcutService.throwForInvalidTag(depth, tag);
+        }
+        return new ShortcutInfo(
+                id, packageName, activityComponent, /* icon =*/ null, title, intent,
+                intentPersistableExtras, weight, extras, lastChangedTimestamp, flags,
+                iconRes, bitmapPath);
     }
 }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 5490260..5fd196b 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -50,6 +50,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.SELinux;
 import android.os.ServiceManager;
 import android.os.ShellCommand;
 import android.os.UserHandle;
@@ -640,7 +641,16 @@
 
     @Override
     public UserInfo getUserInfo(int userId) {
-        checkManageUsersPermission("query user");
+        int callingUserId = UserHandle.getCallingUserId();
+        if (callingUserId != userId && !hasManageUsersPermission()) {
+            synchronized (mPackagesLock) {
+                if (!isSameProfileGroupLP(callingUserId, userId)) {
+                    throw new SecurityException(
+                            "You need MANAGE_USERS permission to: query users outside profile" +
+                                    " group");
+                }
+            }
+        }
         synchronized (mUsersLock) {
             return getUserInfoLU(userId);
         }
@@ -758,23 +768,28 @@
     }
 
     @Override
-    public ParcelFileDescriptor getUserIcon(int userId) {
+    public ParcelFileDescriptor getUserIcon(int targetUserId) {
         String iconPath;
         synchronized (mPackagesLock) {
-            UserInfo info = getUserInfoNoChecks(userId);
-            if (info == null || info.partial) {
-                Slog.w(LOG_TAG, "getUserIcon: unknown user #" + userId);
+            UserInfo targetUserInfo = getUserInfoNoChecks(targetUserId);
+            if (targetUserInfo == null || targetUserInfo.partial) {
+                Slog.w(LOG_TAG, "getUserIcon: unknown user #" + targetUserId);
                 return null;
             }
-            int callingGroupId = getUserInfoNoChecks(UserHandle.getCallingUserId()).profileGroupId;
-            if (callingGroupId == UserInfo.NO_PROFILE_GROUP_ID
-                    || callingGroupId != info.profileGroupId) {
+
+            final int callingUserId = UserHandle.getCallingUserId();
+            final int callingGroupId = getUserInfoNoChecks(callingUserId).profileGroupId;
+            final int targetGroupId = targetUserInfo.profileGroupId;
+            final boolean sameGroup = (callingGroupId != UserInfo.NO_PROFILE_GROUP_ID
+                    && callingGroupId == targetGroupId);
+            if ((callingUserId != targetUserId) && !sameGroup) {
                 checkManageUsersPermission("get the icon of a user who is not related");
             }
-            if (info.iconPath == null) {
+
+            if (targetUserInfo.iconPath == null) {
                 return null;
             }
-            iconPath = info.iconPath;
+            iconPath = targetUserInfo.iconPath;
         }
 
         try {
@@ -1190,18 +1205,28 @@
      *
      * @param message used as message if SecurityException is thrown
      * @throws SecurityException if the caller is not system or root
+     * @see #hasManageUsersPermission()
      */
     private static final void checkManageUsersPermission(String message) {
-        final int uid = Binder.getCallingUid();
-        if (!UserHandle.isSameApp(uid, Process.SYSTEM_UID) && uid != Process.ROOT_UID
-                && ActivityManager.checkComponentPermission(
-                        android.Manifest.permission.MANAGE_USERS,
-                        uid, -1, true) != PackageManager.PERMISSION_GRANTED) {
+        if (!hasManageUsersPermission()) {
             throw new SecurityException("You need MANAGE_USERS permission to: " + message);
         }
     }
 
     /**
+     * @return whether the calling UID is system UID or root's UID or the calling app has the
+     * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}.
+     */
+    private static final boolean hasManageUsersPermission() {
+        final int callingUid = Binder.getCallingUid();
+        return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
+                || callingUid == Process.ROOT_UID
+                || ActivityManager.checkComponentPermission(
+                        android.Manifest.permission.MANAGE_USERS,
+                        callingUid, -1, true) == PackageManager.PERMISSION_GRANTED;
+    }
+
+    /**
      * Enforces that only the system UID or root's UID (on any user) can make certain calls to the
      * UserManager.
      *
@@ -1229,7 +1254,7 @@
             }
             FileOutputStream os;
             if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(tmp))
-                    && tmp.renameTo(file)) {
+                    && tmp.renameTo(file) && SELinux.restorecon(file)) {
                 info.iconPath = file.getAbsolutePath();
             }
             try {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 1603f1c..0115a08 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -191,6 +191,9 @@
     static final int LONG_PRESS_POWER_SHUT_OFF = 2;
     static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
 
+    static final int LONG_PRESS_BACK_NOTHING = 0;
+    static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1;
+
     static final int MULTI_PRESS_POWER_NOTHING = 0;
     static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
     static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
@@ -211,6 +214,13 @@
     static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
     static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;
 
+    // Controls navigation bar opacity depending on which workspace stacks are currently
+    // visible.
+    // Nav bar is always opaque when either the freeform stack or docked stack is visible.
+    static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0;
+    // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque.
+    static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1;
+
     static final int APPLICATION_MEDIA_SUBLAYER = -2;
     static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
     static final int APPLICATION_PANEL_SUBLAYER = 1;
@@ -244,6 +254,12 @@
     // app shows again. If that doesn't happen for 30s we drop the gesture.
     private static final long PANIC_GESTURE_EXPIRATION = 30000;
 
+    private static final String SYSUI_PACKAGE = "com.android.systemui";
+    private static final String SYSUI_SCREENSHOT_SERVICE =
+            "com.android.systemui.screenshot.TakeScreenshotService";
+    private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER =
+            "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver";
+
     /**
      * Keyguard stuff
      */
@@ -378,6 +394,7 @@
     // handler thread.  We'll need to resolve this someday by teaching the input dispatcher
     // to hold wakelocks during dispatch and eliminating the critical path.
     volatile boolean mPowerKeyHandled;
+    volatile boolean mBackKeyHandled;
     volatile boolean mBeganFromNonInteractive;
     volatile int mPowerKeyPressCounter;
     volatile boolean mEndCallKeyHandled;
@@ -430,6 +447,7 @@
     int mLongPressOnPowerBehavior;
     int mDoublePressOnPowerBehavior;
     int mTriplePressOnPowerBehavior;
+    int mLongPressOnBackBehavior;
     int mShortPressOnSleepBehavior;
     int mShortPressWindowBehavior;
     boolean mAwake;
@@ -539,7 +557,7 @@
     boolean mForceStatusBar;
     boolean mForceStatusBarFromKeyguard;
     private boolean mForceStatusBarTransparent;
-    boolean mForceNavBarOpaque;
+    int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
     boolean mHideLockScreen;
     boolean mForcingShowNavBar;
     int mForcingShowNavBarLayer;
@@ -686,6 +704,7 @@
     private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15;
     private static final int MSG_REQUEST_TRANSIENT_BARS = 16;
     private static final int MSG_REQUEST_TV_PICTURE_IN_PICTURE = 17;
+    private static final int MSG_BACK_LONG_PRESS = 18;
 
     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
@@ -750,6 +769,9 @@
                 case MSG_REQUEST_TV_PICTURE_IN_PICTURE:
                     requestTvPictureInPictureInternal();
                     break;
+                case MSG_BACK_LONG_PRESS:
+                    backLongPress();
+                    break;
             }
         }
     }
@@ -1096,6 +1118,13 @@
         }
     }
 
+    private void cancelPendingBackKeyAction() {
+        if (!mBackKeyHandled) {
+            mBackKeyHandled = true;
+            mHandler.removeMessages(MSG_BACK_LONG_PRESS);
+        }
+    }
+
     private void powerPress(long eventTime, boolean interactive, int count) {
         if (mScreenOnEarly && !mScreenOnFully) {
             Slog.i(TAG, "Suppressed redundant power key press while "
@@ -1203,6 +1232,19 @@
         }
     }
 
+    private void backLongPress() {
+        mBackKeyHandled = true;
+
+        switch (mLongPressOnBackBehavior) {
+            case LONG_PRESS_BACK_NOTHING:
+                break;
+            case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST:
+                Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST);
+                startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
+                break;
+        }
+    }
+
     private void sleepPress(long eventTime) {
         if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
             launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
@@ -1231,6 +1273,10 @@
         return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
     }
 
+    private boolean hasLongPressOnBackBehavior() {
+        return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING;
+    }
+
     private void interceptScreenshotChord() {
         if (mScreenshotChordEnabled
                 && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
@@ -1560,6 +1606,9 @@
         mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive);
 
+        mLongPressOnBackBehavior = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_longPressOnBackBehavior);
+
         mShortPressOnPowerBehavior = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_shortPressOnPowerBehavior);
         mLongPressOnPowerBehavior = mContext.getResources().getInteger(
@@ -1729,8 +1778,8 @@
             mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
         }
 
-        mForceNavBarOpaque = res.getBoolean(
-                com.android.internal.R.bool.config_forceNavBarAlwaysOpaque);
+        mNavBarOpacityMode = res.getInteger(
+                com.android.internal.R.integer.config_navBarOpacityMode);
     }
 
     @Override
@@ -4586,7 +4635,9 @@
         }
 
         // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
-        if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR) {
+        // Also, we don't allow windows in multi-window mode to extend out of the screen.
+        if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR
+                && !win.inMultiWindowMode()) {
             df.left = df.top = -10000;
             df.right = df.bottom = 10000;
             if (attrs.type != TYPE_WALLPAPER) {
@@ -5179,6 +5230,7 @@
                 if (mScreenshotConnection != null) {
                     mContext.unbindService(mScreenshotConnection);
                     mScreenshotConnection = null;
+                    notifyScreenshotError();
                 }
             }
         }
@@ -5190,10 +5242,10 @@
             if (mScreenshotConnection != null) {
                 return;
             }
-            ComponentName cn = new ComponentName("com.android.systemui",
-                    "com.android.systemui.screenshot.TakeScreenshotService");
-            Intent intent = new Intent();
-            intent.setComponent(cn);
+            final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE,
+                    SYSUI_SCREENSHOT_SERVICE);
+            final Intent serviceIntent = new Intent();
+            serviceIntent.setComponent(serviceComponent);
             ServiceConnection conn = new ServiceConnection() {
                 @Override
                 public void onServiceConnected(ComponentName name, IBinder service) {
@@ -5228,17 +5280,35 @@
                         }
                     }
                 }
+
                 @Override
-                public void onServiceDisconnected(ComponentName name) {}
+                public void onServiceDisconnected(ComponentName name) {
+                    notifyScreenshotError();
+                }
             };
-            if (mContext.bindServiceAsUser(
-                    intent, conn, Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
+            if (mContext.bindServiceAsUser(serviceIntent, conn,
+                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
+                    UserHandle.CURRENT)) {
                 mScreenshotConnection = conn;
                 mHandler.postDelayed(mScreenshotTimeout, 10000);
             }
         }
     }
 
+    /**
+     * Notifies the screenshot service to show an error.
+     */
+    private void notifyScreenshotError() {
+        // If the service process is killed, then ask it to clean up after itself
+        final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE,
+                SYSUI_SCREENSHOT_ERROR_RECEIVER);
+        Intent errorIntent = new Intent();
+        errorIntent.setComponent(errorComponent);
+        errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
+                Intent.FLAG_RECEIVER_FOREGROUND);
+        mContext.sendBroadcastAsUser(errorIntent, UserHandle.ALL);
+    }
+
     /** {@inheritDoc} */
     @Override
     public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
@@ -5309,6 +5379,29 @@
 
         // Handle special keys.
         switch (keyCode) {
+            case KeyEvent.KEYCODE_BACK: {
+                if (down) {
+                    mBackKeyHandled = false;
+                    if (hasLongPressOnBackBehavior()) {
+                        Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS);
+                        msg.setAsynchronous(true);
+                        mHandler.sendMessageDelayed(msg,
+                                ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
+                    }
+                } else {
+                    boolean handled = mBackKeyHandled;
+
+                    // Reset back key state
+                    cancelPendingBackKeyAction();
+
+                    // Don't pass back press to app if we've already handled it
+                    if (handled) {
+                        result &= ~ACTION_PASS_TO_USER;
+                    }
+                }
+                break;
+            }
+
             case KeyEvent.KEYCODE_VOLUME_DOWN:
             case KeyEvent.KEYCODE_VOLUME_UP:
             case KeyEvent.KEYCODE_VOLUME_MUTE: {
@@ -7093,7 +7186,7 @@
         // is visible but also when we are resizing for the transitions when docked stack
         // visibility changes.
         mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing;
-        final boolean forceOpaqueSystemBars = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
+        final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
 
         // apply translucent bar vis flags
         WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen
@@ -7118,14 +7211,11 @@
         }
 
         if ((!areTranslucentBarsAllowed() && transWin != mStatusBar)
-                || forceOpaqueSystemBars) {
-            vis &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSLUCENT
-                    | View.SYSTEM_UI_TRANSPARENT);
+                || forceOpaqueStatusBar) {
+            vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
         }
 
-        if (mForceNavBarOpaque) {
-            vis &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
-        }
+        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
 
         if (mForceWindowDrawsStatusBarBackground) {
             vis |= View.STATUS_BAR_TRANSPARENT;
@@ -7199,6 +7289,41 @@
         return vis;
     }
 
+    /**
+     * @return the current visibility flags with the nav-bar opacity related flags toggled based
+     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
+     */
+    private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
+            boolean freeformStackVisible, boolean isDockedDividerResizing) {
+        if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
+            if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
+                visibility = setNavBarOpaqueFlag(visibility);
+            }
+        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
+            if (isDockedDividerResizing) {
+                visibility = setNavBarOpaqueFlag(visibility);
+            } else if (freeformStackVisible) {
+                visibility = setNavBarTranslucentFlag(visibility);
+            } else {
+                visibility = setNavBarOpaqueFlag(visibility);
+            }
+        }
+
+        if (!areTranslucentBarsAllowed()) {
+            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
+        }
+        return visibility;
+    }
+
+    private int setNavBarOpaqueFlag(int visibility) {
+        return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
+    }
+
+    private int setNavBarTranslucentFlag(int visibility) {
+        visibility &= ~View.NAVIGATION_BAR_TRANSPARENT;
+        return visibility |= View.NAVIGATION_BAR_TRANSLUCENT;
+    }
+
     private void clearClearableFlagsLw() {
         int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
         if (newVal != mResettingSystemUiFlags) {
@@ -7326,6 +7451,8 @@
                 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
                 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
         pw.print(prefix);
+                pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior);
+        pw.print(prefix);
                 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
                 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
         pw.print(prefix);
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index f5914faf..d0ee6e0 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -201,13 +201,16 @@
         }
     }
 
-    private void updateOverlayStateLocked() {
+    private void updateOverlayStateLocked(ComponentName exemptedComponent) {
         final long identity = Binder.clearCallingIdentity();
         try {
             AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
             if (appOpsManager != null) {
+                String[] exemptions = (exemptedComponent == null) ? new String[0] :
+                        new String[] { exemptedComponent.getPackageName() };
+
                 appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
-                        mVrModeEnabled, mOverlayToken);
+                        mVrModeEnabled, mOverlayToken, exemptions);
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -230,12 +233,12 @@
     private boolean updateCurrentVrServiceLocked(boolean enabled,
             @NonNull ComponentName component, int userId) {
 
-        // Always send mode change events.
-        changeVrModeLocked(enabled);
-
         boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
                 EnabledComponentsObserver.NO_ERROR);
 
+        // Always send mode change events.
+        changeVrModeLocked(enabled, (enabled && validUserComponent) ? component : null);
+
         if (!enabled || !validUserComponent) {
             // Unbind whatever is running
             if (mCurrentVrService != null) {
@@ -275,8 +278,9 @@
      * Note: Must be called while holding {@code mLock}.
      *
      * @param enabled new state of the VR mode.
+     * @param exemptedComponent a component to exempt from AppOps restrictions for overlays.
      */
-    private void changeVrModeLocked(boolean enabled) {
+    private void changeVrModeLocked(boolean enabled, ComponentName exemptedComponent) {
         if (mVrModeEnabled != enabled) {
             mVrModeEnabled = enabled;
 
@@ -284,7 +288,7 @@
             Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
             setVrModeNative(mVrModeEnabled);
 
-            updateOverlayStateLocked();
+            updateOverlayStateLocked(exemptedComponent);
             onVrModeChangedLocked();
         }
     }
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index ccbdad2..3cf9590 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -441,12 +441,8 @@
         }
 
         // Called during initialization of a given user's wallpaper bookkeeping
-        boolean ensureCropExists() {
-            // if the crop file is not present, copy over the source image to use verbatim
-            if (!cropFile.exists()) {
-                return FileUtils.copyFile(wallpaperFile, cropFile);
-            }
-            return true;
+        boolean cropExists() {
+            return cropFile.exists();
         }
     }
 
@@ -734,8 +730,27 @@
     public void systemRunning() {
         if (DEBUG) Slog.v(TAG, "systemReady");
         WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
-        if (!wallpaper.ensureCropExists()) {
-            clearWallpaperLocked(false, FLAG_SET_SYSTEM, UserHandle.USER_SYSTEM, null);
+        // If we think we're going to be using the system image wallpaper imagery, make
+        // sure we have something to render
+        if (mImageWallpaper.equals(wallpaper.nextWallpaperComponent)) {
+            // No crop file? Make sure we've finished the processing sequence if necessary
+            if (!wallpaper.cropExists()) {
+                if (DEBUG) {
+                    Slog.i(TAG, "No crop; regenerating from source");
+                }
+                generateCrop(wallpaper);
+            }
+            // Still nothing?  Fall back to default.
+            if (!wallpaper.cropExists()) {
+                if (DEBUG) {
+                    Slog.i(TAG, "Unable to regenerate crop; resetting");
+                }
+                clearWallpaperLocked(false, FLAG_SET_SYSTEM, UserHandle.USER_SYSTEM, null);
+            }
+        } else {
+            if (DEBUG) {
+                Slog.i(TAG, "Nondefault wallpaper component; gracefully ignoring");
+            }
         }
         switchWallpaper(wallpaper, null);
         wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
@@ -1645,7 +1660,9 @@
         if (wallpaper == null) {
             wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
             mWallpaperMap.put(userId, wallpaper);
-            wallpaper.ensureCropExists();
+            if (!wallpaper.cropExists()) {
+                generateCrop(wallpaper);
+            }
         }
         boolean success = false;
         try {
@@ -1809,7 +1826,8 @@
                 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success
                         + " id=" + wallpaper.wallpaperId);
                 if (success) {
-                    bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
+                    generateCrop(wallpaper);    // based on the new image + metadata
+                    bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, true, false,
                             wallpaper, null);
                 }
             }
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 55b3c7b..3a5dec9 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -171,17 +171,21 @@
         transformation.setAlpha(mAppToken.isVisible() ? 1 : 0);
     }
 
+    void setNullAnimation() {
+        animation = null;
+        usingTransferredAnimation = false;
+    }
+
     public void clearAnimation() {
         if (animation != null) {
-            animation = null;
             animating = true;
         }
         clearThumbnail();
+        setNullAnimation();
         if (mAppToken.deferClearAllDrawn) {
             mAppToken.allDrawn = false;
             mAppToken.deferClearAllDrawn = false;
         }
-        usingTransferredAnimation = false;
     }
 
     public boolean isAnimating() {
@@ -202,9 +206,9 @@
 
         if (animation != null) {
             toAppAnimator.animation = animation;
-            animation = null;
             toAppAnimator.animating = animating;
             toAppAnimator.animLayerAdjustment = animLayerAdjustment;
+            setNullAnimation();
             animLayerAdjustment = 0;
             toAppAnimator.updateLayers();
             updateLayers();
@@ -311,7 +315,7 @@
                 if (mProlongAnimation == PROLONG_ANIMATION_AT_END) {
                     hasMoreFrames = true;
                 } else {
-                    animation = null;
+                    setNullAnimation();
                     clearThumbnail();
                     if (DEBUG_ANIM) Slog.v(TAG, "Finished animation in " + mAppToken + " @ "
                             + currentTime);
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 9795c93..4ec297e 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -322,23 +322,6 @@
         }
     }
 
-    void setWindowsExiting(boolean exiting) {
-        for (int i = allAppWindows.size() - 1; i >= 0; i--) {
-            WindowState win = allAppWindows.get(i);
-            // If the app already requested to remove its window, we don't modify
-            // its exiting state. Otherwise the stale window won't get removed on
-            // exit and could cause focus to be given to the wrong window.
-            if (!(win.mRemoveOnExit && win.mAnimatingExit)) {
-                win.mAnimatingExit = exiting;
-            }
-            // If we're no longer exiting, remove the window from destroying list
-            if (!win.mAnimatingExit && win.mDestroying) {
-                win.mDestroying = false;
-                service.mDestroySurface.remove(win);
-            }
-        }
-    }
-
     // Here we destroy surfaces which have been marked as eligible by the animator, taking care
     // to ensure the client has finished with them. If the client could still be using them
     // we will skip destruction and try again when the client has stopped.
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 73cea52..5212211 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -29,6 +29,7 @@
 import android.app.ActivityManager.StackId;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.graphics.Region.Op;
 import android.util.DisplayMetrics;
 import android.util.Slog;
 import android.view.Display;
@@ -426,6 +427,10 @@
             win.getTouchableRegion(mTmpRegion);
             mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
         }
+        if (getDockedStackVisibleForUserLocked() != null) {
+            mDividerControllerLocked.getTouchRegion(mTmpRect);
+            mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
+        }
         if (mTapDetector != null) {
             mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion, mNonResizeableRegion);
         }
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 9bceee7..36e8bbb 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -95,6 +95,7 @@
     private long mAnimationDuration;
     private final Interpolator mMinimizedDockInterpolator;
     private float mMaximizeMeetFraction;
+    private final Rect mTouchRegion = new Rect();
 
     DockedStackDividerController(WindowManagerService service, DisplayContent displayContent) {
         mService = service;
@@ -129,6 +130,15 @@
         }
     }
 
+    void setTouchRegion(Rect touchRegion) {
+        mTouchRegion.set(touchRegion);
+    }
+
+    void getTouchRegion(Rect outRegion) {
+        outRegion.set(mTouchRegion);
+        outRegion.offset(mWindow.getFrameLw().left, mWindow.getFrameLw().top);
+    }
+
     private void resetDragResizingChangeReported() {
         final WindowList windowList = mDisplayContent.getWindowList();
         for (int i = windowList.size() - 1; i >= 0; i--) {
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index e42658e..b702180 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -24,6 +24,7 @@
 
 import android.app.ActivityManagerNative;
 import android.graphics.Rect;
+import android.os.Debug;
 import android.os.RemoteException;
 import android.util.Log;
 import android.util.Slog;
@@ -36,6 +37,7 @@
 import com.android.server.input.InputManagerService;
 import com.android.server.input.InputWindowHandle;
 
+import java.io.PrintWriter;
 import java.util.Arrays;
 
 final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
@@ -47,6 +49,9 @@
     // When true, prevents input dispatch from proceeding until set to false again.
     private boolean mInputDispatchFrozen;
 
+    // The reason the input is currently frozen or null if the input isn't frozen.
+    private String mInputFreezeReason = null;
+
     // When true, input dispatch proceeds normally.  Otherwise all events are dropped.
     // Initially false, so that input does not get dispatched until boot is finished at
     // which point the ActivityManager will enable dispatching.
@@ -474,12 +479,16 @@
     }
 
     public void freezeInputDispatchingLw() {
-        if (! mInputDispatchFrozen) {
+        if (!mInputDispatchFrozen) {
             if (DEBUG_INPUT) {
                 Slog.v(TAG_WM, "Freezing input dispatching");
             }
 
             mInputDispatchFrozen = true;
+
+            if (DEBUG_INPUT || true) {
+                mInputFreezeReason = Debug.getCallers(6);
+            }
             updateInputDispatchModeLw();
         }
     }
@@ -491,6 +500,7 @@
             }
 
             mInputDispatchFrozen = false;
+            mInputFreezeReason = null;
             updateInputDispatchModeLw();
         }
     }
@@ -509,4 +519,10 @@
     private void updateInputDispatchModeLw() {
         mService.mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen);
     }
+
+    void dump(PrintWriter pw, String prefix) {
+        if (mInputFreezeReason != null) {
+            pw.println(prefix + "mInputFreezeReason=" + mInputFreezeReason);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 2e424d0..e44b0f3 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -508,10 +508,11 @@
 
             replacing = replacing || w.mWillReplaceWindow;
 
-            // If the app is executing an animation because the keyguard is going away,
-            // keep the wallpaper during the animation so it doesn't flicker out.
+            // If the app is executing an animation because the keyguard is going away (and the
+            // keyguard was showing the wallpaper) keep the wallpaper during the animation so it
+            // doesn't flicker out.
             final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0
-                    || (w.mAppToken != null && w.mWinAnimator.mKeyguardGoingAwayAnimation);
+                    || (w.mAppToken != null && w.mWinAnimator.mKeyguardGoingAwayWithWallpaper);
             if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
                 if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: #" + i + "=" + w);
                 result.setWallpaperTarget(w, i);
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 4698e4e..f243761 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -22,6 +22,9 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
+import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
+import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD;
@@ -98,8 +101,7 @@
     boolean mInitialized = false;
 
     boolean mKeyguardGoingAway;
-    boolean mKeyguardGoingAwayToNotificationShade;
-    boolean mKeyguardGoingAwayDisableWindowAnimations;
+    int mKeyguardGoingAwayFlags;
 
     /** Use one animation for all entering activities after keyguard is dismissed. */
     Animation mPostKeyguardExitAnimation;
@@ -243,6 +245,13 @@
 
         final WindowList windows = mService.getWindowListLocked(displayId);
 
+        final boolean keyguardGoingAwayToShade =
+                (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0;
+        final boolean keyguardGoingAwayNoAnimation =
+                (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0;
+        final boolean keyguardGoingAwayWithWallpaper =
+                (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0;
+
         if (mKeyguardGoingAway) {
             for (int i = windows.size() - 1; i >= 0; i--) {
                 WindowState win = windows.get(i);
@@ -261,6 +270,8 @@
                         winAnimator.mAnimationIsEntrance = false;
                         winAnimator.mAnimationStartTime = -1;
                         winAnimator.mKeyguardGoingAwayAnimation = true;
+                        winAnimator.mKeyguardGoingAwayWithWallpaper
+                                = keyguardGoingAwayWithWallpaper;
                     }
                 } else {
                     if (DEBUG_KEYGUARD) Slog.d(TAG,
@@ -392,10 +403,13 @@
                             if (DEBUG_KEYGUARD) Slog.v(TAG,
                                     "Applying existing Keyguard exit animation to new window: win="
                                             + win);
-                            Animation a = mPolicy.createForceHideEnterAnimation(
-                                    false, mKeyguardGoingAwayToNotificationShade);
+
+                            Animation a = mPolicy.createForceHideEnterAnimation(false,
+                                    keyguardGoingAwayToShade);
                             winAnimator.setAnimation(a, mPostKeyguardExitAnimation.getStartTime());
                             winAnimator.mKeyguardGoingAwayAnimation = true;
+                            winAnimator.mKeyguardGoingAwayWithWallpaper
+                                    = keyguardGoingAwayWithWallpaper;
                         }
                         final WindowState currentFocus = mService.mCurrentFocus;
                         if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
@@ -463,18 +477,20 @@
         // being force-hidden, apply the appropriate animation to them if animations are not
         // disabled.
         if (unForceHiding != null) {
-            if (!mKeyguardGoingAwayDisableWindowAnimations) {
+            if (!keyguardGoingAwayNoAnimation) {
                 boolean first = true;
                 for (int i=unForceHiding.size()-1; i>=0; i--) {
                     final WindowStateAnimator winAnimator = unForceHiding.get(i);
                     Animation a = mPolicy.createForceHideEnterAnimation(
                             wallpaperInUnForceHiding && !startingInUnForceHiding,
-                            mKeyguardGoingAwayToNotificationShade);
+                            keyguardGoingAwayToShade);
                     if (a != null) {
                         if (DEBUG_KEYGUARD) Slog.v(TAG,
                                 "Starting keyguard exit animation on window " + winAnimator.mWin);
                         winAnimator.setAnimation(a);
                         winAnimator.mKeyguardGoingAwayAnimation = true;
+                        winAnimator.mKeyguardGoingAwayWithWallpaper
+                                = keyguardGoingAwayWithWallpaper;
                         if (first) {
                             mPostKeyguardExitAnimation = a;
                             mPostKeyguardExitAnimation.setStartTime(mCurrentTime);
@@ -489,11 +505,10 @@
 
 
             // Wallpaper is going away in un-force-hide motion, animate it as well.
-            if (!wallpaperInUnForceHiding && wallpaper != null
-                    && !mKeyguardGoingAwayDisableWindowAnimations) {
+            if (!wallpaperInUnForceHiding && wallpaper != null && !keyguardGoingAwayNoAnimation) {
                 if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away");
                 Animation a = mPolicy.createForceHideWallpaperExitAnimation(
-                        mKeyguardGoingAwayToNotificationShade);
+                        keyguardGoingAwayToShade);
                 if (a != null) {
                     wallpaper.mWinAnimator.setAnimation(a);
                 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a998bc3..607a3e9 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2626,7 +2626,8 @@
                 }
 
                 // Odd choice but less odd than embedding in copyFrom()
-                if ((attrs.flags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY) != 0) {
+                if ((attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY)
+                        != 0) {
                     attrs.x = win.mAttrs.x;
                     attrs.y = win.mAttrs.y;
                     attrs.width = win.mAttrs.width;
@@ -2825,10 +2826,12 @@
         if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
             focusMayChange = isDefaultDisplay;
             win.mAnimatingExit = true;
+            win.mWinAnimator.mAnimating = true;
         } else if (win.mWinAnimator.isAnimating()) {
             // Currently in a hide animation... turn this into
             // an exit.
             win.mAnimatingExit = true;
+            win.mWinAnimator.mAnimating = true;
         } else if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
             // If the wallpaper is currently behind this
             // window, we need to change both of them inside
@@ -4085,7 +4088,7 @@
 
             if (transit != AppTransition.TRANSIT_UNSET) {
                 if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
-                    wtoken.mAppAnimator.animation = null;
+                    wtoken.mAppAnimator.setNullAnimation();
                 }
                 if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) {
                     delayed = runningAppAnimation = true;
@@ -4195,7 +4198,7 @@
     void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) {
         if (transit != AppTransition.TRANSIT_UNSET) {
             if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) {
-                wtoken.mAppAnimator.animation = null;
+                wtoken.mAppAnimator.setNullAnimation();
             }
             applyAnimationLocked(wtoken, null, transit, false, false);
         }
@@ -4252,17 +4255,12 @@
                 wtoken.appDied = false;
                 wtoken.removeAllWindows();
             } else if (visible) {
-                if (DEBUG_ADD_REMOVE) Slog.v(
-                        TAG_WM, "No longer Stopped: " + wtoken);
-                wtoken.mAppStopped = false;
-                wtoken.setWindowsExiting(false);
                 mOpeningApps.add(wtoken);
                 wtoken.startingMoved = false;
 
-                // If the token is currently hidden (should be the
-                // common case), then we need to set up to wait for
-                // its windows to be ready.
-                if (wtoken.hidden) {
+                // If the token is currently hidden (should be the common case), or has been
+                // stopped, then we need to set up to wait for its windows to be ready.
+                if (wtoken.hidden || wtoken.mAppStopped) {
                     wtoken.allDrawn = false;
                     wtoken.deferClearAllDrawn = false;
                     wtoken.waitingToShow = true;
@@ -4278,6 +4276,9 @@
                         wtoken.sendAppVisibilityToClients();
                     }
                 }
+                if (DEBUG_ADD_REMOVE) Slog.v(
+                        TAG_WM, "No longer Stopped: " + wtoken);
+                wtoken.mAppStopped = false;
             }
 
             // If we are preparing an app transition, then delay changing
@@ -4287,6 +4288,11 @@
                 // animation is going on (in this case an application transition). If the animation
                 // was transferred from another application/animator, no dummy animator should be
                 // created since an animation is already in progress.
+                if (wtoken.mAppAnimator.usingTransferredAnimation
+                        && wtoken.mAppAnimator.animation == null) {
+                    Slog.wtf(TAG_WM, "Will NOT set dummy animation on: " + wtoken
+                            + ", using null transfered animation!");
+                }
                 if (!wtoken.mAppAnimator.usingTransferredAnimation &&
                         (!wtoken.startingDisplayed || mSkipAppTransitionAnimation)) {
                     if (DEBUG_APP_TRANSITIONS) Slog.v(
@@ -4297,7 +4303,6 @@
                 if (visible) {
                     wtoken.mEnteringAnimation = true;
                 } else {
-                    wtoken.setWindowsExiting(true);
                     mClosingApps.add(wtoken);
                     wtoken.mEnteringAnimation = false;
                 }
@@ -5173,18 +5178,16 @@
     }
 
     @Override
-    public void keyguardGoingAway(boolean disableWindowAnimations,
-            boolean keyguardGoingToNotificationShade) {
+    public void keyguardGoingAway(int flags) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
         }
-        if (DEBUG_KEYGUARD) Slog.d(TAG_WM, "keyguardGoingAway: disableWinAnim="
-                + disableWindowAnimations + " kgToNotifShade=" + keyguardGoingToNotificationShade);
+        if (DEBUG_KEYGUARD) Slog.d(TAG_WM,
+                "keyguardGoingAway: flags=0x" + Integer.toHexString(flags));
         synchronized (mWindowMap) {
             mAnimator.mKeyguardGoingAway = true;
-            mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade;
-            mAnimator.mKeyguardGoingAwayDisableWindowAnimations = disableWindowAnimations;
+            mAnimator.mKeyguardGoingAwayFlags = flags;
             mWindowPlacerLocked.requestTraversal();
         }
     }
@@ -9907,6 +9910,9 @@
                     pw.print(mLastFinishedFreezeSource);
                 }
                 pw.println();
+
+        mInputMonitor.dump(pw, "  ");
+
         if (dumpAll) {
             pw.print("  mSystemDecorLayer="); pw.print(mSystemDecorLayer);
                     pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString());
@@ -10438,6 +10444,15 @@
     }
 
     @Override
+    public void setDockedStackDividerTouchRegion(Rect touchRegion) {
+        synchronized (mWindowMap) {
+            getDefaultDisplayContentLocked().getDockedDividerController()
+                    .setTouchRegion(touchRegion);
+            setFocusTaskRegionLocked();
+        }
+    }
+
+    @Override
     public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
         synchronized (mWindowMap) {
             getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer(
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 910788e..1695615 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -642,18 +642,26 @@
         mHaveFrame = true;
 
         final Task task = getTask();
-        final boolean fullscreenTask = task == null || task.isFullscreen();
+        final boolean fullscreenTask = !inMultiWindowMode();
         final boolean windowsAreFloating = task != null && task.isFloating();
 
-        if (fullscreenTask || (isChildWindow()
-                && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0)) {
+        // If the task has temp inset bounds set, we have to make sure all its windows uses
+        // the temp inset frame. Otherwise different display frames get applied to the main
+        // window and the child window, making them misaligned.
+        if (fullscreenTask) {
+            mInsetFrame.setEmpty();
+        } else {
+            task.getTempInsetBounds(mInsetFrame);
+        }
+
+        if (mInsetFrame.isEmpty()  && (fullscreenTask
+                || (isChildWindow() && (mAttrs.privateFlags
+                        & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0))) {
             // We use the parent frame as the containing frame for fullscreen and child windows
             mContainingFrame.set(pf);
             mDisplayFrame.set(df);
-            mInsetFrame.setEmpty();
         } else {
             task.getBounds(mContainingFrame);
-            task.getTempInsetBounds(mInsetFrame);
             if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) {
 
                 // If the bounds are frozen, we still want to translate the window freely and only
@@ -670,8 +678,8 @@
             }
 
             if (windowsAreFloating) {
-                // In floating modes (e.g. freeform, pinned) we have only to set the rectangle 
-                // if it wasn't set already. No need to intersect it with the (visible) 
+                // In floating modes (e.g. freeform, pinned) we have only to set the rectangle
+                // if it wasn't set already. No need to intersect it with the (visible)
                 // "content frame" since it is allowed to be outside the visible desktop.
                 if (mContainingFrame.isEmpty()) {
                     mContainingFrame.set(cf);
@@ -2215,6 +2223,12 @@
         return task != null && task.inFreeformWorkspace();
     }
 
+    @Override
+    public boolean inMultiWindowMode() {
+        final Task task = getTask();
+        return task != null && !task.isFullscreen();
+    }
+
     boolean isDragResizeChanged() {
         return mDragResizing != computeDragResizing();
     }
@@ -2506,9 +2520,8 @@
         final int pw = mContainingFrame.width();
         final int ph = mContainingFrame.height();
         final Task task = getTask();
-        final boolean nonFullscreenTask = task != null && !task.isFullscreen();
-        final boolean fitToDisplay = task != null &&
-            !task.isFloating();
+        final boolean nonFullscreenTask = inMultiWindowMode();
+        final boolean fitToDisplay = task != null && !task.isFloating();
         float x, y;
         int w,h;
 
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index bf8a62e..41eafe7 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -160,6 +160,7 @@
     boolean mEnteringAnimation;
 
     boolean mKeyguardGoingAwayAnimation;
+    boolean mKeyguardGoingAwayWithWallpaper;
 
     /** The pixel format of the underlying SurfaceControl */
     int mSurfaceFormat;
@@ -250,6 +251,7 @@
             mAnimation.cancel();
             mAnimation = null;
             mKeyguardGoingAwayAnimation = false;
+            mKeyguardGoingAwayWithWallpaper = false;
         }
     }
 
@@ -381,6 +383,7 @@
 
         mAnimating = false;
         mKeyguardGoingAwayAnimation = false;
+        mKeyguardGoingAwayWithWallpaper = false;
         mLocalAnimating = false;
         if (mAnimation != null) {
             mAnimation.cancel();
@@ -708,8 +711,6 @@
 
         // Start a new transaction and apply position & offset.
         final int layerStack = w.getDisplayContent().getDisplay().getLayerStack();
-        if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
-                "POS " + mTmpSize.left + ", " + mTmpSize.top, false);
         mSurfaceController.setPositionAndLayer(mTmpSize.left, mTmpSize.top, layerStack, mAnimLayer);
         mLastHidden = true;
 
@@ -1216,17 +1217,17 @@
         }
 
         // We don't apply the stack bounds crop if:
-        // 1. The window is currently animating docked mode or in freeform mode, otherwise the
-        // animating window will be suddenly (docked) or for whole animation (freeform) cut off.
-        // (Note that we still need to apply the crop if the task being docked is non-resizeable,
-        // in which case the task is running in fullscreen size but cropped to stack bounds.)
+        // 1. The window is currently animating in freeform mode, otherwise the animating window
+        // will be suddenly (docked) or for whole animation (freeform) cut off.
         // 2. The window that is being replaced during animation, because it was living in a
         // different stack. If we suddenly crop it to the new stack bounds, it might get cut off.
         // We don't want it to happen, so we let it ignore the stack bounds until it gets removed.
         // The window that will replace it will abide them.
-        if (isAnimating() && (w.mWillReplaceWindow
-                || (w.inDockedWorkspace() && task.isResizeable())
-                || w.inFreeformWorkspace())) {
+        // TODO: identify animations where we don't want to apply docked stack crop to the docked
+        //       task. For example, if the app is going from freeform to docked mode, we may not
+        //       want to apply the crop during the animation, since it will make the app appear
+        //       cropped prematurely.
+        if (isAnimating() && (w.mWillReplaceWindow || w.inFreeformWorkspace())) {
             return;
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index fb07512..11f3771 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -119,6 +119,8 @@
             mSurfaceY = top;
 
             try {
+                if (SHOW_TRANSACTIONS) logSurface(
+                        "POS (setPositionAndLayer) @ (" + left + "," + top + ")", null);
                 mSurfaceControl.setPosition(left, top);
                 mSurfaceControl.setLayerStack(layerStack);
 
@@ -205,6 +207,9 @@
             mSurfaceY = top;
 
             try {
+                if (SHOW_TRANSACTIONS) logSurface(
+                        "POS (setPositionInTransaction) @ (" + left + "," + top + ")", null);
+
                 mSurfaceControl.setPosition(left, top);
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Error positioning surface of " + this
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 8ada2f1..5ad771f 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -1158,7 +1158,7 @@
 
             if (!appAnimator.usingTransferredAnimation) {
                 appAnimator.clearThumbnail();
-                appAnimator.animation = null;
+                appAnimator.setNullAnimation();
             }
             wtoken.inPendingTransaction = false;
 
@@ -1231,7 +1231,7 @@
             final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
             appAnimator.clearThumbnail();
-            appAnimator.animation = null;
+            appAnimator.setNullAnimation();
             wtoken.inPendingTransaction = false;
             mService.setTokenVisibilityLocked(wtoken, animLp, false, transit, false,
                     voiceInteraction);
@@ -1494,7 +1494,7 @@
                 if (DEBUG_APP_TRANSITIONS)
                     Slog.v(TAG, "Now animating app in place " + wtoken);
                 appAnimator.clearThumbnail();
-                appAnimator.animation = null;
+                appAnimator.setNullAnimation();
                 mService.updateTokenInPlaceLocked(wtoken, transit);
                 wtoken.updateReportedVisibilityLocked();
 
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 60ed497..e2c71a1 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1087,8 +1087,25 @@
 const char *const JavaMethodHelper<bool>::signature_ = "(Z)V";
 
 #define SET(setter, value) object.callSetter("set" # setter, (value))
-#define SET_IF(flag, setter, value) \
-        if (flags & (flag)) object.callSetter("set" # setter, (value))
+
+// If you want to check if a flag is not set, use SET_IF_NOT(FLAG, setter,
+// value) to do that. SET_IF(!FLAG, setter, value) won't compile.
+//
+// This macros generates compilation error if the provided 'flag' is not a
+// single token. For example, 'GNSS_CLOCK_HAS_BIAS' can be accepted, but
+// '!GNSS_CLOCK_HAS_DRIFT' will fail to compile.
+#define SET_IF(flag, setter, value) do { \
+        if (flags & flag) { \
+            JavaObject& name_check_##flag = object; \
+            name_check_##flag.callSetter("set" # setter, (value)); \
+        } \
+    } while (false)
+#define SET_IF_NOT(flag, setter, value) do { \
+        if (!(flags & flag)) { \
+            JavaObject& name_check_##flag = object; \
+            name_check_##flag.callSetter("set" # setter, (value)); \
+        } \
+    } while (false)
 
 static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
     static uint32_t discontinuity_count_to_handle_old_lock_type = 0;
@@ -1209,6 +1226,10 @@
         static_cast<int32_t>(measurement->multipath_indicator));
     SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
 
+    SET_IF_NOT(GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE,
+               PseudorangeRateCorrected,
+               true);
+
     return object.get();
 }
 
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index 6c640ba..c4316f6 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -400,7 +400,7 @@
                 connection.mThread->shutdown();
             }
             connection.mThread = new BufferProducerThread(mDevice, deviceId, &stream);
-            connection.mThread->run();
+            connection.mThread->run("BufferProducerThread");
         }
     }
     connection.mSurface = surface;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9a75dc9..6ddc6c8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -26,13 +26,12 @@
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
 import static org.xmlpull.v1.XmlPullParser.TEXT;
 
-import com.google.android.collect.Sets;
-
 import android.Manifest.permission;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accounts.AccountManager;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -49,10 +48,10 @@
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.IDevicePolicyManager;
+import android.app.admin.SecurityLog;
+import android.app.admin.SecurityLog.SecurityEvent;
 import android.app.admin.SystemUpdatePolicy;
 import android.app.backup.IBackupManager;
-import android.auditing.SecurityLog;
-import android.auditing.SecurityLog.SecurityEvent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -83,6 +82,7 @@
 import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Build;
+import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.FileUtils;
@@ -113,6 +113,7 @@
 import android.security.KeyChain;
 import android.security.KeyChain.KeyChainConnection;
 import android.service.persistentdata.PersistentDataBlockManager;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -139,6 +140,7 @@
 import com.android.server.SystemService;
 import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
 import com.android.server.pm.UserRestrictionsUtils;
+import com.google.android.collect.Sets;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -304,6 +306,7 @@
     final IPackageManager mIPackageManager;
     final UserManager mUserManager;
     final UserManagerInternal mUserManagerInternal;
+    final TelephonyManager mTelephonyManager;
     private final LockPatternUtils mLockPatternUtils;
 
     /**
@@ -480,9 +483,9 @@
                 new MonitoringCertNotificationTask().execute(intent);
             }
             if (Intent.ACTION_USER_ADDED.equals(action)) {
-                disableDeviceLoggingIfNotCompliant();
+                disableSecurityLoggingIfNotCompliant();
             } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
-                disableDeviceLoggingIfNotCompliant();
+                disableSecurityLoggingIfNotCompliant();
                 removeUserData(userHandle);
             } else if (Intent.ACTION_USER_STARTED.equals(action)) {
                 synchronized (DevicePolicyManagerService.this) {
@@ -1352,6 +1355,10 @@
             return LocalServices.getService(PowerManagerInternal.class);
         }
 
+        TelephonyManager getTelephonyManager() {
+            return TelephonyManager.from(mContext);
+        }
+
         IWindowManager getIWindowManager() {
             return IWindowManager.Stub
                     .asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
@@ -1378,6 +1385,22 @@
             return new LockPatternUtils(mContext);
         }
 
+        boolean storageManagerIsFileBasedEncryptionEnabled() {
+            return StorageManager.isFileEncryptedNativeOnly();
+        }
+
+        boolean storageManagerIsNonDefaultBlockEncrypted() {
+            return StorageManager.isNonDefaultBlockEncrypted();
+        }
+
+        boolean storageManagerIsEncrypted() {
+            return StorageManager.isEncrypted();
+        }
+
+        boolean storageManagerIsEncryptable() {
+            return StorageManager.isEncryptable();
+        }
+
         Looper getMyLooper() {
             return Looper.myLooper();
         }
@@ -1524,6 +1547,7 @@
         mUserManager = Preconditions.checkNotNull(injector.getUserManager());
         mUserManagerInternal = Preconditions.checkNotNull(injector.getUserManagerInternal());
         mIPackageManager = Preconditions.checkNotNull(injector.getIPackageManager());
+        mTelephonyManager = Preconditions.checkNotNull(injector.getTelephonyManager());
 
         mLocalService = new LocalService();
         mLockPatternUtils = injector.newLockPatternUtils();
@@ -1642,16 +1666,18 @@
         }
 
         if (!TextUtils.isEmpty(mInjector.systemPropertiesGet(PROPERTY_DEVICE_OWNER_PRESENT))) {
-            Slog.wtf(LOG_TAG, "Trying to set ro.device_owner, but it has already been set?");
+            Slog.w(LOG_TAG, "Trying to set ro.device_owner, but it has already been set?");
         } else {
             if (mOwners.hasDeviceOwner()) {
                 mInjector.systemPropertiesSet(PROPERTY_DEVICE_OWNER_PRESENT, "true");
-                disableDeviceLoggingIfNotCompliant();
+                Slog.i(LOG_TAG, "Set ro.device_owner property to true");
+                disableSecurityLoggingIfNotCompliant();
                 if (mInjector.securityLogGetLoggingEnabledProperty()) {
                     mSecurityLogMonitor.start();
                 }
             } else {
                 mInjector.systemPropertiesSet(PROPERTY_DEVICE_OWNER_PRESENT, "false");
+                Slog.i(LOG_TAG, "Set ro.device_owner property to false");
             }
         }
     }
@@ -2866,13 +2892,9 @@
     @Override
     public boolean isSeparateProfileChallengeAllowed(int userHandle) {
         ComponentName profileOwner = getProfileOwner(userHandle);
-        try {
-            // Profile challenge is supported on N or newer release.
-            return profileOwner != null &&
-                    getTargetSdk(profileOwner.getPackageName(), userHandle) > Build.VERSION_CODES.M;
-        } catch (RemoteException e) {
-            return false;
-        }
+        // Profile challenge is supported on N or newer release.
+        return profileOwner != null &&
+                getTargetSdk(profileOwner.getPackageName(), userHandle) > Build.VERSION_CODES.M;
     }
 
     @Override
@@ -4236,15 +4258,12 @@
         int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-            try {
-                if (getTargetSdk(who.getPackageName(), userHandle) >= Build.VERSION_CODES.N) {
-                    if (installerPackage != null &&
-                            !isPackageInstalledForUser(installerPackage, userHandle)) {
-                        throw new IllegalArgumentException("Package " + installerPackage
-                                + " is not installed on the current user");
-                    }
+            if (getTargetSdk(who.getPackageName(), userHandle) >= Build.VERSION_CODES.N) {
+                if (installerPackage != null &&
+                        !isPackageInstalledForUser(installerPackage, userHandle)) {
+                    throw new IllegalArgumentException("Package " + installerPackage
+                            + " is not installed on the current user");
                 }
-            } catch (RemoteException e) {
             }
             DevicePolicyData policy = getUserData(userHandle);
             policy.mDelegatedCertInstallerPackage = installerPackage;
@@ -4835,12 +4854,23 @@
      * Get the current encryption status of the device.
      */
     @Override
-    public int getStorageEncryptionStatus(int userHandle) {
+    public int getStorageEncryptionStatus(@Nullable String callerPackage, int userHandle) {
         if (!mHasFeature) {
             // Ok to return current status.
         }
         enforceFullCrossUsersPermission(userHandle);
-        return getEncryptionStatus();
+
+        // It's not critical here, but let's make sure the package name is correct, in case
+        // we start using it for different purposes.
+        ensureCallerPackage(callerPackage);
+
+        final int rawStatus = getEncryptionStatus();
+        if ((rawStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER)
+                && (callerPackage != null)
+                && (getTargetSdk(callerPackage, userHandle) <= VERSION_CODES.M)) {
+            return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE;
+        }
+        return rawStatus;
     }
 
     /**
@@ -4858,15 +4888,18 @@
      * Hook to low-levels:  Reporting the current status of encryption.
      * @return A value such as {@link DevicePolicyManager#ENCRYPTION_STATUS_UNSUPPORTED},
      * {@link DevicePolicyManager#ENCRYPTION_STATUS_INACTIVE},
-     * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY}, or
+     * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY},
+     * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE_PER_USER}, or
      * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE}.
      */
     private int getEncryptionStatus() {
-        if (!StorageManager.isNonDefaultBlockEncrypted()) {
-            return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY;
-        } else if (StorageManager.isEncrypted()) {
+        if (mInjector.storageManagerIsFileBasedEncryptionEnabled()) {
+            return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
+        } else if (mInjector.storageManagerIsNonDefaultBlockEncrypted()) {
             return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE;
-        } else if (StorageManager.isEncryptable()) {
+        } else if (mInjector.storageManagerIsEncrypted()) {
+            return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY;
+        } else if (mInjector.storageManagerIsEncryptable()) {
             return DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
         } else {
             return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
@@ -4879,7 +4912,6 @@
     private void setEncryptionRequested(boolean encrypt) {
     }
 
-
     /**
      * Set whether the screen capture is disabled for the user managed by the specified admin.
      */
@@ -5579,7 +5611,7 @@
             mOwners.clearDeviceOwner();
             mOwners.writeDeviceOwner();
             updateDeviceOwnerLocked();
-            disableDeviceLoggingIfNotCompliant();
+            disableSecurityLoggingIfNotCompliant();
             // Reactivate backup service.
             long ident = mInjector.binderClearCallingIdentity();
             try {
@@ -6037,6 +6069,23 @@
         }
     }
 
+    private void ensureCallerPackage(@Nullable String packageName) {
+        if (packageName == null) {
+            Preconditions.checkState(isCallerWithSystemUid(),
+                    "Only caller can omit package name");
+        } else {
+            final int callingUid = mInjector.binderGetCallingUid();
+            final int userId = mInjector.userHandleGetCallingUserId();
+            try {
+                final ApplicationInfo ai = mIPackageManager.getApplicationInfo(
+                        packageName, 0, userId);
+                Preconditions.checkState(ai.uid == callingUid, "Unmatching package name");
+            } catch (RemoteException e) {
+                // Shouldn't happen
+            }
+        }
+    }
+
     private boolean isCallerWithSystemUid() {
         return UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID);
     }
@@ -6122,6 +6171,27 @@
                 pw.println(" ");
                 pw.print("    mPasswordOwner="); pw.println(policy.mPasswordOwner);
             }
+            pw.println();
+            pw.println("Encryption Status: " + getEncryptionStatusName(getEncryptionStatus()));
+        }
+    }
+
+    private String getEncryptionStatusName(int encryptionStatus) {
+        switch (encryptionStatus) {
+            case DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE:
+                return "inactive";
+            case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY:
+                return "block default key";
+            case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE:
+                return "block";
+            case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER:
+                return "per-user";
+            case DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED:
+                return "unsupported";
+            case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVATING:
+                return "activating";
+            default:
+                return "unknown";
         }
     }
 
@@ -7831,6 +7901,29 @@
             }
             return false;
         }
+
+        @Override
+        public Intent createPackageSuspendedDialogIntent(String packageName, int userId) {
+            Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
+            intent.putExtra(Intent.EXTRA_USER_ID, userId);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            synchronized (DevicePolicyManagerService.this) {
+                ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId);
+                if (profileOwner != null) {
+                    intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, profileOwner);
+                    return intent;
+                }
+
+                if (mOwners.getDeviceOwnerUserId() == userId) {
+                    ComponentName deviceOwner = mOwners.getDeviceOwnerComponent();
+                    if (deviceOwner != null) {
+                        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, deviceOwner);
+                        return intent;
+                    }
+                }
+            }
+            return null;
+        }
     }
 
     /**
@@ -8207,11 +8300,16 @@
      * Returns the target sdk version number that the given packageName was built for
      * in the given user.
      */
-    private int getTargetSdk(String packageName, int userId) throws RemoteException {
-        final ApplicationInfo ai = mIPackageManager
-                .getApplicationInfo(packageName, 0, userId);
-        final int targetSdkVersion = ai == null ? 0 : ai.targetSdkVersion;
-        return targetSdkVersion;
+    private int getTargetSdk(String packageName, int userId) {
+        final ApplicationInfo ai;
+        try {
+            ai = mIPackageManager.getApplicationInfo(packageName, 0, userId);
+            final int targetSdkVersion = ai == null ? 0 : ai.targetSdkVersion;
+            return targetSdkVersion;
+        } catch (RemoteException e) {
+            // Shouldn't happen
+            return 0;
+        }
     }
 
     @Override
@@ -8242,6 +8340,10 @@
         }
         long ident = mInjector.binderClearCallingIdentity();
         try {
+            // Make sure there are no ongoing calls on the device.
+            if (mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
+                throw new IllegalStateException("Cannot be called with ongoing call on the device");
+            }
             mInjector.powerManagerReboot(PowerManager.REBOOT_REQUESTED_BY_DEVICE_OWNER);
         } finally {
             mInjector.binderRestoreCallingIdentity(ident);
@@ -8495,15 +8597,15 @@
         return false;
     }
 
-    private synchronized void disableDeviceLoggingIfNotCompliant() {
+    private synchronized void disableSecurityLoggingIfNotCompliant() {
         if (!isDeviceOwnerManagedSingleUserDevice()) {
             mInjector.securityLogSetLoggingEnabledProperty(false);
-            Slog.w(LOG_TAG, "Device logging turned off as it's no longer a single user device.");
+            Slog.w(LOG_TAG, "Security logging turned off as it's no longer a single user device.");
         }
     }
 
     @Override
-    public void setDeviceLoggingEnabled(ComponentName admin, boolean enabled) {
+    public void setSecurityLoggingEnabled(ComponentName admin, boolean enabled) {
         Preconditions.checkNotNull(admin);
         ensureDeviceOwnerManagingSingleUser(admin);
 
@@ -8521,7 +8623,7 @@
     }
 
     @Override
-    public boolean getDeviceLoggingEnabled(ComponentName admin) {
+    public boolean isSecurityLoggingEnabled(ComponentName admin) {
         Preconditions.checkNotNull(admin);
         synchronized (this) {
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -8530,7 +8632,7 @@
     }
 
     @Override
-    public ParceledListSlice<SecurityEvent> retrievePreviousDeviceLogs(ComponentName admin) {
+    public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin) {
         Preconditions.checkNotNull(admin);
         ensureDeviceOwnerManagingSingleUser(admin);
 
@@ -8545,7 +8647,7 @@
     }
 
     @Override
-    public ParceledListSlice<SecurityEvent> retrieveDeviceLogs(ComponentName admin) {
+    public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin) {
         Preconditions.checkNotNull(admin);
         ensureDeviceOwnerManagingSingleUser(admin);
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
index cacc671..79702a8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
@@ -17,8 +17,8 @@
 package com.android.server.devicepolicy;
 
 import android.app.admin.DeviceAdminReceiver;
-import android.auditing.SecurityLog;
-import android.auditing.SecurityLog.SecurityEvent;
+import android.app.admin.SecurityLog;
+import android.app.admin.SecurityLog.SecurityEvent;
 import android.util.Log;
 import android.util.Slog;
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 59f8284a..5975405 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -28,6 +28,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources.Theme;
+import android.os.BaseBundle;
 import android.os.Build;
 import android.os.Environment;
 import android.os.FactoryTest;
@@ -35,7 +36,6 @@
 import android.os.IPowerManager;
 import android.os.Looper;
 import android.os.PowerManager;
-import android.os.RecoverySystem;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StrictMode;
@@ -53,6 +53,7 @@
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.SamplingProfilerIntegration;
 import com.android.internal.os.ZygoteInit;
+import com.android.internal.widget.ILockSettings;
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.accounts.AccountManagerService;
 import com.android.server.am.ActivityManagerService;
@@ -69,10 +70,9 @@
 import com.android.server.input.InputManagerService;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.lights.LightsService;
-import com.android.internal.widget.ILockSettings;
+import com.android.server.media.MediaResourceMonitorService;
 import com.android.server.media.MediaRouterService;
 import com.android.server.media.MediaSessionService;
-import com.android.server.media.MediaResourceMonitorService;
 import com.android.server.media.projection.MediaProjectionManagerService;
 import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.net.NetworkStatsService;
@@ -271,6 +271,10 @@
             // explicitly specifying a user.
             Environment.setUserRequired(true);
 
+            // Within the system server, any incoming Bundles should be defused
+            // to avoid throwing BadParcelableException.
+            BaseBundle.setShouldDefuse(true);
+
             // Ensure binder calls into the system always run at foreground priority.
             BinderInternal.disableBackgroundScheduling(true);
 
@@ -518,6 +522,16 @@
         boolean disableNetwork = SystemProperties.getBoolean("config.disable_network", false);
         boolean disableNetworkTime = SystemProperties.getBoolean("config.disable_networktime", false);
         boolean disableRtt = SystemProperties.getBoolean("config.disable_rtt", false);
+        boolean disableMediaProjection = SystemProperties.getBoolean("config.disable_mediaproj",
+                false);
+        boolean disableSerial = SystemProperties.getBoolean("config.disable_serial", false);
+        boolean disableSearchManager = SystemProperties.getBoolean("config.disable_searchmanager",
+                false);
+        boolean disableTrustManager = SystemProperties.getBoolean("config.disable_trustmanager",
+                false);
+        boolean disableTextServices = SystemProperties.getBoolean("config.disable_textservices", false);
+        boolean disableSamplingProfiler = SystemProperties.getBoolean("config.disable_samplingprof",
+                false);
         boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1");
 
         try {
@@ -726,9 +740,6 @@
                 // Always start the Device Policy Manager, so that the API is compatible with
                 // API8.
                 mSystemServiceManager.startService(DevicePolicyManagerService.Lifecycle.class);
-
-// TODO is this a good place?
-                mSystemServiceManager.startService(ShortcutService.Lifecycle.class);
             }
 
             if (!disableSystemUI) {
@@ -764,7 +775,7 @@
                 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
-            if (!disableNonCoreServices) {
+            if (!disableNonCoreServices && !disableTextServices) {
                 mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class);
             }
 
@@ -915,7 +926,7 @@
                 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
 
-            if (!disableNonCoreServices) {
+            if (!disableNonCoreServices && !disableSearchManager) {
                 traceBeginAndSlog("StartSearchManagerService");
                 try {
                     mSystemServiceManager.startService(SEARCH_MANAGER_SERVICE_CLASS);
@@ -977,15 +988,17 @@
                     Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
                 }
 
-                traceBeginAndSlog("StartSerialService");
-                try {
-                    // Serial port support
-                    serial = new SerialService(context);
-                    ServiceManager.addService(Context.SERIAL_SERVICE, serial);
-                } catch (Throwable e) {
-                    Slog.e(TAG, "Failure starting SerialService", e);
+                if (!disableSerial) {
+                    traceBeginAndSlog("StartSerialService");
+                    try {
+                        // Serial port support
+                        serial = new SerialService(context);
+                        ServiceManager.addService(Context.SERIAL_SERVICE, serial);
+                    } catch (Throwable e) {
+                        Slog.e(TAG, "Failure starting SerialService", e);
+                    }
+                    Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
                 }
-                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
                 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER,
                         "StartHardwarePropertiesManagerService");
@@ -1023,6 +1036,7 @@
                     mSystemServiceManager.startService(GestureLauncherService.class);
                 }
                 mSystemServiceManager.startService(SensorNotificationService.class);
+                mSystemServiceManager.startService(ContextHubSystemService.class);
             }
 
             traceBeginAndSlog("StartDiskStatsService");
@@ -1033,18 +1047,20 @@
             }
             Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
-            traceBeginAndSlog("StartSamplingProfilerService");
-            try {
-                // need to add this service even if SamplingProfilerIntegration.isEnabled()
-                // is false, because it is this service that detects system property change and
-                // turns on SamplingProfilerIntegration. Plus, when sampling profiler doesn't work,
-                // there is little overhead for running this service.
-                ServiceManager.addService("samplingprofiler",
-                            new SamplingProfilerService(context));
-            } catch (Throwable e) {
-                reportWtf("starting SamplingProfiler Service", e);
+            if (!disableSamplingProfiler) {
+                traceBeginAndSlog("StartSamplingProfilerService");
+                try {
+                    // need to add this service even if SamplingProfilerIntegration.isEnabled()
+                    // is false, because it is this service that detects system property change and
+                    // turns on SamplingProfilerIntegration. Plus, when sampling profiler doesn't work,
+                    // there is little overhead for running this service.
+                    ServiceManager.addService("samplingprofiler",
+                                new SamplingProfilerService(context));
+                } catch (Throwable e) {
+                    reportWtf("starting SamplingProfiler Service", e);
+                }
+                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
-            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
             if (!disableNetwork && !disableNetworkTime) {
                 traceBeginAndSlog("StartNetworkTimeUpdateService");
@@ -1125,7 +1141,9 @@
                 }
                 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
-                mSystemServiceManager.startService(TrustManagerService.class);
+                if (!disableTrustManager) {
+                    mSystemServiceManager.startService(TrustManagerService.class);
+                }
 
                 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
                     mSystemServiceManager.startService(FingerprintService.class);
@@ -1139,11 +1157,13 @@
                 }
                 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
             }
+            // LauncherAppsService uses ShortcutService.
+            mSystemServiceManager.startService(ShortcutService.Lifecycle.class);
 
             mSystemServiceManager.startService(LauncherAppsService.class);
         }
 
-        if (!disableNonCoreServices) {
+        if (!disableNonCoreServices && !disableMediaProjection) {
             mSystemServiceManager.startService(MediaProjectionManagerService.class);
         }
 
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_1024x4096.png b/services/tests/servicestests/res/drawable-nodpi/black_1024x4096.png
new file mode 100644
index 0000000..f700326
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_1024x4096.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_16x64.png b/services/tests/servicestests/res/drawable-nodpi/black_16x64.png
new file mode 100644
index 0000000..315763e
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_16x64.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_32x32.png b/services/tests/servicestests/res/drawable-nodpi/black_32x32.png
new file mode 100644
index 0000000..8958f6b
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_32x32.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_4096x1024.png b/services/tests/servicestests/res/drawable-nodpi/black_4096x1024.png
new file mode 100644
index 0000000..f675030
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_4096x1024.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_4096x4096.png b/services/tests/servicestests/res/drawable-nodpi/black_4096x4096.png
new file mode 100644
index 0000000..999d858
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_4096x4096.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_512x512.png b/services/tests/servicestests/res/drawable-nodpi/black_512x512.png
new file mode 100644
index 0000000..40d1c2c
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_512x512.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_64x16.png b/services/tests/servicestests/res/drawable-nodpi/black_64x16.png
new file mode 100644
index 0000000..5883015
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_64x16.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/black_64x64.png b/services/tests/servicestests/res/drawable-nodpi/black_64x64.png
new file mode 100644
index 0000000..71cfafc
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/black_64x64.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/icon1.png b/services/tests/servicestests/res/drawable-nodpi/icon1.png
new file mode 100644
index 0000000..64eb294
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/icon1.png
Binary files differ
diff --git a/services/tests/servicestests/res/drawable-nodpi/icon2.png b/services/tests/servicestests/res/drawable-nodpi/icon2.png
new file mode 100644
index 0000000..75024841
--- /dev/null
+++ b/services/tests/servicestests/res/drawable-nodpi/icon2.png
Binary files differ
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 69f12eb..34f2e2e 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -161,9 +161,11 @@
                 assertNull("BUG: only one idle handler allowed", mIdleHandler);
                 mIdleHandler = new IdleHandler() {
                     public boolean queueIdle() {
-                        cv.open();
-                        mIdleHandler = null;
-                        return false;  // Remove the handler.
+                        synchronized (queue) {
+                            cv.open();
+                            mIdleHandler = null;
+                            return false;  // Remove the handler.
+                        }
                     }
                 };
                 queue.addIdleHandler(mIdleHandler);
diff --git a/services/tests/servicestests/src/com/android/server/DropBoxTest.java b/services/tests/servicestests/src/com/android/server/DropBoxTest.java
index 055ce76..7f28d44 100644
--- a/services/tests/servicestests/src/com/android/server/DropBoxTest.java
+++ b/services/tests/servicestests/src/com/android/server/DropBoxTest.java
@@ -54,7 +54,7 @@
     public void testAddText() throws Exception {
         File dir = getEmptyDir("testAddText");
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         long before = System.currentTimeMillis();
         Thread.sleep(5);
@@ -90,7 +90,7 @@
     public void testAddData() throws Exception {
         File dir = getEmptyDir("testAddData");
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         long before = System.currentTimeMillis();
         dropbox.addData("DropBoxTest", "TEST".getBytes(), 0);
@@ -135,7 +135,7 @@
         gz3.close();
 
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         dropbox.addFile("DropBoxTest", f0, DropBoxManager.IS_TEXT);
         dropbox.addFile("DropBoxTest", f1, DropBoxManager.IS_TEXT | DropBoxManager.IS_GZIPPED);
@@ -201,7 +201,7 @@
         new FileOutputStream(new File(dir, "DropBoxTest@" + (before + 100002) + ".lost")).close();
 
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         // Until a write, the timestamps are taken at face value
         DropBoxManager.Entry e0 = dropbox.getNextEntry(null, before);
@@ -252,7 +252,7 @@
     public void testIsTagEnabled() throws Exception {
         File dir = getEmptyDir("testIsTagEnabled");
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         long before = System.currentTimeMillis();
         dropbox.addText("DropBoxTest", "TEST-ENABLED");
@@ -285,7 +285,7 @@
     public void testGetNextEntry() throws Exception {
         File dir = getEmptyDir("testGetNextEntry");
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         long before = System.currentTimeMillis();
         dropbox.addText("DropBoxTest.A", "A0");
@@ -347,7 +347,7 @@
         final int overhead = 64;
         long before = System.currentTimeMillis();
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         addRandomEntry(dropbox, "DropBoxTest0", blockSize - overhead);
         addRandomEntry(dropbox, "DropBoxTest0", blockSize - overhead);
@@ -441,7 +441,7 @@
         // Write one normal entry and another so big that it is instantly tombstoned
         long before = System.currentTimeMillis();
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         dropbox.addText("DropBoxTest", "TEST");
         addRandomEntry(dropbox, "DropBoxTest", blockSize * 20);
@@ -472,7 +472,7 @@
         File dir = getEmptyDir("testFileCountLimits");
 
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
         dropbox.addText("DropBoxTest", "TEST0");
         dropbox.addText("DropBoxTest", "TEST1");
         dropbox.addText("DropBoxTest", "TEST2");
@@ -525,7 +525,7 @@
         File dir = new File(getEmptyDir("testCreateDropBoxManagerWith"), "InvalidDirectory");
         new FileOutputStream(dir).close();  // Create an empty file
         DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
-        DropBoxManager dropbox = new DropBoxManager(service.getServiceStub());
+        DropBoxManager dropbox = new DropBoxManager(getContext(), service.getServiceStub());
 
         dropbox.addText("DropBoxTest", "should be ignored");
         dropbox.addData("DropBoxTest", "should be ignored".getBytes(), 0);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index db2a9ad..35777ce 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -28,6 +28,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
+import android.os.storage.StorageManager;
+import android.telephony.TelephonyManager;
 import android.view.IWindowManager;
 
 import java.io.File;
@@ -163,6 +165,26 @@
         }
 
         @Override
+        boolean storageManagerIsFileBasedEncryptionEnabled() {
+            return context.storageManager.isFileBasedEncryptionEnabled();
+        }
+
+        @Override
+        boolean storageManagerIsNonDefaultBlockEncrypted() {
+            return context.storageManager.isNonDefaultBlockEncrypted();
+        }
+
+        @Override
+        boolean storageManagerIsEncrypted() {
+            return context.storageManager.isEncrypted();
+        }
+
+        @Override
+        boolean storageManagerIsEncryptable() {
+            return context.storageManager.isEncryptable();
+        }
+
+        @Override
         String getDevicePolicyFilePathForSystemUser() {
             return context.systemUserDataDir.getAbsolutePath() + "/";
         }
@@ -301,5 +323,10 @@
         boolean securityLogIsLoggingEnabled() {
             return context.settings.securityLogIsLoggingEnabled();
         }
+
+        @Override
+        TelephonyManager getTelephonyManager() {
+            return context.telephonyManager;
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index e897e3d..6c2bdda 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -33,6 +33,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.telephony.TelephonyManager;
 import android.test.MoreAsserts;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.ArraySet;
@@ -1491,7 +1492,7 @@
         assertEquals("11:22:33:44:55:66", dpm.getWifiMacAddress(admin1));
     }
 
-    public void testRebootCanOnlyBeCalledByDeviceOwner() throws Exception {
+    public void testReboot() throws Exception {
         mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
 
@@ -1524,6 +1525,29 @@
         dpm.clearProfileOwner(admin1);
         assertTrue(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM));
 
+        // admin1 is DO.
+        // Set current call state of device to ringing.
+        when(mContext.telephonyManager.getCallState())
+                .thenReturn(TelephonyManager.CALL_STATE_RINGING);
+        try {
+            dpm.reboot(admin1);
+            fail("DPM.reboot() called when receiveing a call, should thrown IllegalStateException");
+        } catch (IllegalStateException expected) {
+            MoreAsserts.assertContainsRegex("ongoing call on the device", expected.getMessage());
+        }
+
+        // Set current call state of device to dialing/active.
+        when(mContext.telephonyManager.getCallState())
+                .thenReturn(TelephonyManager.CALL_STATE_OFFHOOK);
+        try {
+            dpm.reboot(admin1);
+            fail("DPM.reboot() called when dialing, should thrown IllegalStateException");
+        } catch (IllegalStateException expected) {
+            MoreAsserts.assertContainsRegex("ongoing call on the device", expected.getMessage());
+        }
+
+        // Set current call state of device to idle.
+        when(mContext.telephonyManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_IDLE);
         dpm.reboot(admin1);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index ef8e420..8e2ef70 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -39,6 +39,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
+import android.os.storage.StorageManager;
+import android.telephony.TelephonyManager;
 import android.test.mock.MockContentResolver;
 import android.test.mock.MockContext;
 import android.view.IWindowManager;
@@ -211,6 +213,24 @@
         }
     }
 
+    public static class StorageManagerForMock {
+        public boolean isFileBasedEncryptionEnabled() {
+            return false;
+        }
+
+        public boolean isNonDefaultBlockEncrypted() {
+            return false;
+        }
+
+        public boolean isEncrypted() {
+            return false;
+        }
+
+        public boolean isEncryptable() {
+            return false;
+        }
+    }
+
     public final Context realTestContext;
 
     /**
@@ -239,9 +259,11 @@
     public final IBackupManager ibackupManager;
     public final IAudioService iaudioService;
     public final LockPatternUtils lockPatternUtils;
+    public final StorageManagerForMock storageManager;
     public final WifiManager wifiManager;
     public final SettingsForMock settings;
     public final MockContentResolver contentResolver;
+    public final TelephonyManager telephonyManager;
 
     /** Note this is a partial mock, not a real mock. */
     public final PackageManager packageManager;
@@ -272,8 +294,10 @@
         ibackupManager = mock(IBackupManager.class);
         iaudioService = mock(IAudioService.class);
         lockPatternUtils = mock(LockPatternUtils.class);
+        storageManager = mock(StorageManagerForMock.class);
         wifiManager = mock(WifiManager.class);
         settings = mock(SettingsForMock.class);
+        telephonyManager = mock(TelephonyManager.class);
 
         // Package manager is huge, so we use a partial mock instead.
         packageManager = spy(context.getPackageManager());
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
index b9e9aa9..82c6b6d 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
@@ -25,7 +25,7 @@
 import static org.mockito.Mockito.when;
 
 import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.ROAMING_DEFAULT;
+import static android.net.NetworkStats.ROAMING_NO;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkTemplate.buildTemplateMobileAll;
 import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
@@ -447,7 +447,7 @@
         // Baseline
         NetworkStats xtSnapshot = null;
         NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                         BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -455,7 +455,7 @@
 
         // Delta
         uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                         BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -487,7 +487,7 @@
         // Baseline
         NetworkStats xtSnapshot = null;
         NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                         BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -495,7 +495,7 @@
 
         // Delta
         uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                         BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -527,7 +527,7 @@
         // Baseline
         NetworkStats xtSnapshot = null;
         NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                         BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -535,7 +535,7 @@
 
         // Delta
         uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                         BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -567,7 +567,7 @@
         // Baseline
         NetworkStats xtSnapshot = null;
         NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                         BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -575,7 +575,7 @@
 
         // Delta
         uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                         BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -607,7 +607,7 @@
         // Baseline
         NetworkStats xtSnapshot = null;
         NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+                .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                         BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
@@ -615,7 +615,7 @@
 
         // Delta
         uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
-                .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+                .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                         BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java
index 4f6c7b9..74c1984 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java
@@ -23,8 +23,8 @@
 import static android.net.ConnectivityManager.TYPE_WIMAX;
 import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.ROAMING_ALL;
-import static android.net.NetworkStats.ROAMING_DEFAULT;
-import static android.net.NetworkStats.ROAMING_ROAMING;
+import static android.net.NetworkStats.ROAMING_NO;
+import static android.net.NetworkStats.ROAMING_YES;
 import static android.net.NetworkStats.SET_ALL;
 import static android.net.NetworkStats.SET_DEFAULT;
 import static android.net.NetworkStats.SET_FOREGROUND;
@@ -321,8 +321,8 @@
         // verify service recorded history
         assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0);
         assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10);
-        assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, ROAMING_DEFAULT, 512L, 4L, 256L, 2L, 4);
-        assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_DEFAULT, 512L, 4L, 256L, 2L,
+        assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, ROAMING_NO, 512L, 4L, 256L, 2L, 4);
+        assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L,
                 6);
         assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0);
         verifyAndReset();
@@ -357,8 +357,8 @@
         // after systemReady(), we should have historical stats loaded again
         assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0);
         assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10);
-        assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, ROAMING_DEFAULT, 512L, 4L, 256L, 2L, 4);
-        assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_DEFAULT, 512L, 4L, 256L, 2L,
+        assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, ROAMING_NO, 512L, 4L, 256L, 2L, 4);
+        assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L,
                 6);
         assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0);
         verifyAndReset();
@@ -711,11 +711,11 @@
         NetworkStats stats = mSession.getSummaryForAllUid(
                 sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
         assertEquals(3, stats.size());
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 50L, 5L,
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 50L, 5L,
                 50L, 5L, 1);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 10L, 1L, 10L,
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 10L, 1L, 10L,
                 1L, 1);
-        assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 2048L, 16L,
+        assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_NO, 2048L, 16L,
                 1024L, 8L, 0);
 
         // now verify that recent history only contains one uid
@@ -723,7 +723,7 @@
         stats = mSession.getSummaryForAllUid(
                 sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true);
         assertEquals(1, stats.size());
-        assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L,
+        assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L,
                 512L, 4L, 0);
 
         verifyAndReset();
@@ -787,13 +787,13 @@
         final NetworkStats stats = mSession.getSummaryForAllUid(
                 sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
         assertEquals(4, stats.size());
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 2L,
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 2L,
                 128L, 2L, 1);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 64L, 1L, 64L,
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L,
                 1L, 1);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 32L, 2L,
+        assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 32L, 2L,
                 32L, 2L, 1);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, ROAMING_DEFAULT, 1L, 1L, 1L,
+        assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, ROAMING_NO, 1L, 1L, 1L,
                 1L, 1);
 
         verifyAndReset();
@@ -818,13 +818,13 @@
         expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
-        // Note that all traffic from NetworkManagementService is tagged as ROAMING_DEFAULT, because
+        // Note that all traffic from NetworkManagementService is tagged as ROAMING_NO, because
         // roaming isn't tracked at that layer. We layer it on top by inspecting the iface
         // properties.
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 2L,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 2L,
                         128L, 2L, 0L)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 64L, 1L, 64L,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L,
                         1L, 0L));
         expectNetworkStatsPoll();
 
@@ -838,9 +838,9 @@
         final NetworkStats stats = mSession.getSummaryForAllUid(
                 sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true);
         assertEquals(2, stats.size());
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 128L, 2L,
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 2L,
                 128L, 2L, 0);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_ROAMING, 64L, 1L, 64L,
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_YES, 64L, 1L, 64L,
                 1L, 0);
 
         verifyAndReset();
@@ -1073,9 +1073,9 @@
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 2L,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 2L,
                         128L, 2L, 0L)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 64L, 1L, 64L,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L,
                         1L, 0L));
         expectNetworkStatsPoll();
 
@@ -1089,9 +1089,9 @@
         NetworkStats stats = mSession.getSummaryForAllUid(
                 sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true);
         assertEquals(2, stats.size());
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 128L, 2L,
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 2L,
                 128L, 2L, 0);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_ROAMING, 64L, 1L, 64L,
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_YES, 64L, 1L, 64L,
                 1L, 0);
 
         verifyAndReset();
@@ -1106,9 +1106,9 @@
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO,
                         128000000L, 2L, 128000000L, 2L, 0L)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT,
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO,
                         64000000L, 1L, 64000000L, 1L, 0L));
         expectNetworkStatsPoll();
 
@@ -1122,9 +1122,9 @@
         stats = mSession.getSummaryForAllUid(
                 sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true);
         assertEquals(2, stats.size());
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING,
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_YES,
                 128000000L, 2L, 128000000L, 2L, 0);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_ROAMING,
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_YES,
                 64000000L, 1L, 64000000L, 1L, 0);
 
         verifyAndReset();
@@ -1180,7 +1180,7 @@
 
         // verify summary API
         final NetworkStats stats = mSession.getSummaryForNetwork(template, start, end);
-        assertValues(stats, IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, rxBytes,
+        assertValues(stats, IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, rxBytes,
                 rxPackets, txBytes, txPackets, operations);
     }
 
@@ -1312,11 +1312,11 @@
         }
 
         List<Integer> roamings = new ArrayList<>();
-        if (roaming == ROAMING_DEFAULT || roaming == ROAMING_ALL) {
-            roamings.add(ROAMING_DEFAULT);
+        if (roaming == ROAMING_NO || roaming == ROAMING_ALL) {
+            roamings.add(ROAMING_NO);
         }
-        if (roaming == ROAMING_ROAMING || roaming == ROAMING_ALL) {
-            roamings.add(ROAMING_ROAMING);
+        if (roaming == ROAMING_YES || roaming == ROAMING_ALL) {
+            roamings.add(ROAMING_YES);
         }
 
         for (int s : sets) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
index 1f805e9..6bcaf4d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -15,43 +15,76 @@
  */
 package com.android.server.pm;
 
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.app.Activity;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ILauncherApps;
+import android.content.pm.LauncherApps;
 import android.content.pm.LauncherApps.ShortcutQuery;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
 import android.content.pm.ShortcutServiceInternal;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.Icon;
+import android.os.BaseBundle;
 import android.os.Bundle;
 import android.os.FileUtils;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
 import android.os.UserHandle;
-import android.test.AndroidTestCase;
+import android.os.UserManager;
+import android.test.InstrumentationTestCase;
 import android.test.mock.MockContext;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 
 import com.android.frameworks.servicestests.R;
 import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.pm.LauncherAppsService.LauncherAppsImpl;
+import com.android.server.pm.ShortcutService.ConfigConstants;
+import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
+
+import libcore.io.IoUtils;
 
 import org.junit.Assert;
+import org.mockito.ArgumentCaptor;
 
 import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileReader;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Tests for ShortcutService and ShortcutManager.
@@ -61,18 +94,54 @@
  -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
  adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest \
  -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+
+ * TODO: Add checks with assertAllNotHaveIcon()
+ *
+ * TODO: separate, detailed tests for ShortcutInfo (CTS?) *
+ *
+ * TODO: Cross-user test (do in CTS?)
+ *
  */
-public class ShortcutManagerTest extends AndroidTestCase {
+@SmallTest
+public class ShortcutManagerTest extends InstrumentationTestCase {
     private static final String TAG = "ShortcutManagerTest";
 
     /**
      * Whether to enable dump or not.  Should be only true when debugging to avoid bugs where
      * dump affecting the behavior.
      */
-    private static final boolean ENABLE_DUMP = true; // DO NOT SUBMIT WITH true
+    private static final boolean ENABLE_DUMP = false; // DO NOT SUBMIT WITH true
+
+    private class BaseContext extends MockContext {
+        @Override
+        public Object getSystemService(String name) {
+            switch (name) {
+                case Context.USER_SERVICE:
+                    return mMockUserManager;
+            }
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public PackageManager getPackageManager() {
+            return mMockPackageManager;
+        }
+
+        @Override
+        public Resources getResources() {
+            return getTestContext().getResources();
+        }
+
+        @Override
+        public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
+                IntentFilter filter, String broadcastPermission, Handler scheduler) {
+            // ignore.
+            return null;
+        }
+    }
 
     /** Context used in the client side */
-    private final class ClientContext extends MockContext {
+    private class ClientContext extends BaseContext {
         @Override
         public String getPackageName() {
             return mInjectedClientPackage;
@@ -80,21 +149,52 @@
     }
 
     /** Context used in the service side */
-    private final class ServiceContext extends MockContext {
+    private final class ServiceContext extends BaseContext {
+        long injectClearCallingIdentity() {
+            final int prevCallingUid = mInjectedCallingUid;
+            mInjectedCallingUid = Process.SYSTEM_UID;
+            return prevCallingUid;
+        }
+
+        void injectRestoreCallingIdentity(long token) {
+            mInjectedCallingUid = (int) token;
+        }
     }
 
     /** ShortcutService with injection override methods. */
     private final class ShortcutServiceTestable extends ShortcutService {
-        public ShortcutServiceTestable(Context context) {
-            super(context);
+        final ServiceContext mContext;
 
+        public ShortcutServiceTestable(ServiceContext context) {
+            super(context);
+            mContext = context;
         }
 
         @Override
-        void injectLoadConfigurationLocked() {
-            setResetIntervalForTest(INTERVAL);
-            setMaxDynamicShortcutsForTest(MAX_SHORTCUTS);
-            setMaxDailyUpdatesForTest(MAX_DAILY_UPDATES);
+        String injectShortcutManagerConstants() {
+            return ConfigConstants.KEY_RESET_INTERVAL_SEC + "=" + (INTERVAL / 1000) + ","
+                    + ConfigConstants.KEY_MAX_SHORTCUTS + "=" + MAX_SHORTCUTS + ","
+                    + ConfigConstants.KEY_MAX_DAILY_UPDATES + "=" + MAX_DAILY_UPDATES + ","
+                    + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=" + MAX_ICON_DIMENSION + ","
+                    + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "="
+                    + MAX_ICON_DIMENSION_LOWRAM + ","
+                    + ConfigConstants.KEY_ICON_FORMAT + "=PNG,"
+                    + ConfigConstants.KEY_ICON_QUALITY + "=100";
+        }
+
+        @Override
+        long injectClearCallingIdentity() {
+            return mContext.injectClearCallingIdentity();
+        }
+
+        @Override
+        void injectRestoreCallingIdentity(long token) {
+            mContext.injectRestoreCallingIdentity(token);
+        }
+
+        @Override
+        int injectDipToPixel(int dip) {
+            return dip;
         }
 
         @Override
@@ -108,9 +208,9 @@
         }
 
         @Override
-        int injectGetPackageUid(String packageName) {
+        int injectGetPackageUid(String packageName, int userId) {
             Integer uid = mInjectedPackageUidMap.get(packageName);
-            return uid != null ? uid : -1;
+            return UserHandle.getUid(getCallingUserId(), (uid != null ? uid : 0));
         }
 
         @Override
@@ -122,10 +222,38 @@
         File injectUserDataPath(@UserIdInt int userId) {
             return new File(mInjectedFilePathRoot, "user-" + userId);
         }
+
+        @Override
+        void injectValidateIconResPackage(ShortcutInfo shortcut, Icon icon) {
+            // Can't check
+        }
+
+        @Override
+        boolean injectIsLowRamDevice() {
+            return mInjectdIsLowRamDevice;
+        }
+
+        @Override
+        PackageManagerInternal injectPackageManagerInternal() {
+            return mMockPackageManagerInternal;
+        }
+
+        @Override
+        boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
+            // Sort of hack; do a simpler check.
+            return LAUNCHER_1.equals(callingPackage) || LAUNCHER_2.equals(callingPackage);
+        }
+
+        @Override
+        void postToHandler(Runnable r) {
+            final long token = mContext.injectClearCallingIdentity();
+            r.run();
+            mContext.injectRestoreCallingIdentity(token);
+        }
     }
 
     /** ShortcutManager with injection override methods. */
-    private final class ShortcutManagerTestable extends ShortcutManager {
+    private class ShortcutManagerTestable extends ShortcutManager {
         public ShortcutManagerTestable(Context context, ShortcutServiceTestable service) {
             super(context, service);
         }
@@ -136,6 +264,49 @@
         }
     }
 
+    private class LauncherAppImplTestable extends LauncherAppsImpl {
+        final ServiceContext mContext;
+
+        public LauncherAppImplTestable(ServiceContext context) {
+            super(context);
+            mContext = context;
+        }
+
+        @Override
+        public void ensureInUserProfiles(UserHandle userToCheck, String message) {
+            if (getCallingUserId() == userToCheck.getIdentifier()) {
+                return; // okay
+            }
+
+            assertEquals(Process.SYSTEM_UID, mInjectedCallingUid);
+            // SKIP
+        }
+
+        @Override
+        public void verifyCallingPackage(String callingPackage) {
+            // SKIP
+        }
+
+        @Override
+        boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser, String debugMsg) {
+            // This requires CROSS_USER
+            assertEquals(Process.SYSTEM_UID, mInjectedCallingUid);
+            return user.getIdentifier() == listeningUser.getIdentifier();
+        }
+
+        @Override
+        void postToPackageMonitor(Runnable r) {
+            final long token = mContext.injectClearCallingIdentity();
+            r.run();
+            mContext.injectRestoreCallingIdentity(token);
+        }
+    }
+
+    private class LauncherAppsTestable extends LauncherApps {
+        public LauncherAppsTestable(Context context, ILauncherApps service) {
+            super(context, service);
+        }
+    }
 
     public static class ShortcutActivity extends Activity {
     }
@@ -153,15 +324,24 @@
     private ShortcutManagerTestable mManager;
     private ShortcutServiceInternal mInternal;
 
+    private LauncherAppImplTestable mLauncherAppImpl;
+    private LauncherAppsTestable mLauncherApps;
+
     private File mInjectedFilePathRoot;
 
     private long mInjectedCurrentTimeLillis;
 
+    private boolean mInjectdIsLowRamDevice;
+
     private int mInjectedCallingUid;
     private String mInjectedClientPackage;
 
     private Map<String, Integer> mInjectedPackageUidMap;
 
+    private PackageManager mMockPackageManager;
+    private PackageManagerInternal mMockPackageManagerInternal;
+    private UserManager mMockUserManager;
+
     private static final String CALLING_PACKAGE_1 = "com.android.test.1";
     private static final int CALLING_UID_1 = 10001;
 
@@ -177,14 +357,22 @@
     private static final String LAUNCHER_2 = "com.android.launcher.2";
     private static final int LAUNCHER_UID_2 = 10012;
 
+    private static final int USER_0 = UserHandle.USER_SYSTEM;
+    private static final int USER_10 = 10;
+    private static final int USER_11 = 11;
+
     private static final long START_TIME = 1234560000000L;
 
     private static final long INTERVAL = 10000;
 
-    private static final int MAX_SHORTCUTS = 5;
+    private static final int MAX_SHORTCUTS = 10;
 
     private static final int MAX_DAILY_UPDATES = 3;
 
+    private static final int MAX_ICON_DIMENSION = 128;
+
+    private static final int MAX_ICON_DIMENSION_LOWRAM = 32;
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -192,6 +380,10 @@
         mServiceContext = new ServiceContext();
         mClientContext = new ClientContext();
 
+        mMockPackageManager = mock(PackageManager.class);
+        mMockPackageManagerInternal = mock(PackageManagerInternal.class);
+        mMockUserManager = mock(UserManager.class);
+
         // Prepare injection values.
 
         mInjectedCurrentTimeLillis = START_TIME;
@@ -203,7 +395,7 @@
         mInjectedPackageUidMap.put(LAUNCHER_1, LAUNCHER_UID_1);
         mInjectedPackageUidMap.put(LAUNCHER_2, LAUNCHER_UID_2);
 
-        mInjectedFilePathRoot = new File(getContext().getCacheDir(), "test-files");
+        mInjectedFilePathRoot = new File(getTestContext().getCacheDir(), "test-files");
 
         // Empty the data directory.
         if (mInjectedFilePathRoot.exists()) {
@@ -216,6 +408,10 @@
         setCaller(CALLING_PACKAGE_1);
     }
 
+    private Context getTestContext() {
+        return getInstrumentation().getContext();
+    }
+
     /** (Re-) init the manager and the service. */
     private void initService() {
         LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
@@ -226,24 +422,48 @@
 
         mInternal = LocalServices.getService(ShortcutServiceInternal.class);
 
+        mLauncherAppImpl = new LauncherAppImplTestable(mServiceContext);
+        mLauncherApps = new LauncherAppsTestable(mClientContext, mLauncherAppImpl);
+
         // Load the setting file.
         mService.onBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
     }
 
     /** Replace the current calling package */
-    private void setCaller(String packageName) {
+    private void setCaller(String packageName, int userId) {
         mInjectedClientPackage = packageName;
-        mInjectedCallingUid = Preconditions.checkNotNull(mInjectedPackageUidMap.get(packageName));
+        mInjectedCallingUid = UserHandle.getUid(userId,
+                Preconditions.checkNotNull(mInjectedPackageUidMap.get(packageName),
+                        "Unknown package"));
+    }
+
+    private void setCaller(String packageName) {
+        setCaller(packageName, UserHandle.USER_SYSTEM);
     }
 
     private String getCallingPackage() {
         return mInjectedClientPackage;
     }
 
+    private void runWithCaller(String packageName, int userId, Runnable r) {
+        final String previousPackage = mInjectedClientPackage;
+        final int previousUid = mInjectedCallingUid;
+
+        setCaller(packageName, userId);
+
+        r.run();
+
+        setCaller(previousPackage, previousUid);
+    }
+
     private int getCallingUserId() {
         return UserHandle.getUserId(mInjectedCallingUid);
     }
 
+    private UserHandle getCallingUser() {
+        return UserHandle.of(getCallingUserId());
+    }
+
     /** For debugging */
     private void dumpsysOnLogcat() {
         if (!ENABLE_DUMP) return;
@@ -295,6 +515,10 @@
                 + "/" + ShortcutService.FILENAME_USER_PACKAGES);
     }
 
+    private void waitOnMainThread() throws Throwable {
+        runTestOnUiThread(() -> {});
+    }
+
     private static Bundle makeBundle(Object... keysAndValues) {
         Preconditions.checkState((keysAndValues.length % 2) == 0);
 
@@ -343,6 +567,27 @@
     }
 
     /**
+     * Make a shortcut with an ID and icon.
+     */
+    private ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
+        return makeShortcut(
+                id, "Title-" + id, /* activity =*/ null, icon,
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* weight =*/ 0);
+    }
+
+    private ShortcutInfo makePackageShortcut(String packageName, String id) {
+        String origCaller = getCallingPackage();
+
+        setCaller(packageName);
+        ShortcutInfo s = makeShortcut(
+                id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* weight =*/ 0);
+        setCaller(origCaller); // restore the caller
+
+        return s;
+    }
+
+    /**
      * Make multiple shortcuts with IDs.
      */
     private List<ShortcutInfo> makeShortcuts(String... ids) {
@@ -353,6 +598,10 @@
         return ret;
     }
 
+    private ShortcutInfo.Builder makeShortcutBuilder() {
+        return new ShortcutInfo.Builder(mClientContext);
+    }
+
     /**
      * Make a shortcut with details.
      */
@@ -413,6 +662,7 @@
     @NonNull
     private List<ShortcutInfo> assertShortcutIds(@NonNull List<ShortcutInfo> actualShortcuts,
             String... expectedIds) {
+        assertEquals(expectedIds.length, actualShortcuts.size());
         final HashSet<String> expected = new HashSet<>(Arrays.asList(expectedIds));
         final HashSet<String> actual = new HashSet<>();
         for (ShortcutInfo s : actualShortcuts) {
@@ -461,6 +711,44 @@
     }
 
     @NonNull
+    private List<ShortcutInfo> assertAllNotHaveIcon(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertNull("ID " + s.getId(), s.getIcon());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllHaveIconResId(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertTrue("ID " + s.getId() + " not have icon res ID", s.hasIconResource());
+            assertFalse("ID " + s.getId() + " shouldn't have icon FD", s.hasIconFile());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllHaveIconFile(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertFalse("ID " + s.getId() + " shouldn't have icon res ID", s.hasIconResource());
+            assertTrue("ID " + s.getId() + " not have icon FD", s.hasIconFile());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllHaveIcon(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertTrue("ID " + s.getId(), s.hasIconFile() || s.hasIconResource());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
     private List<ShortcutInfo> assertAllHaveFlags(@NonNull List<ShortcutInfo> actualShortcuts,
             int shortcutFlags) {
         for (ShortcutInfo s : actualShortcuts) {
@@ -470,6 +758,24 @@
     }
 
     @NonNull
+    private List<ShortcutInfo> assertAllKeyFieldsOnly(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertTrue("ID " + s.getId(), s.hasKeyFieldsOnly());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
+    private List<ShortcutInfo> assertAllNotKeyFieldsOnly(
+            @NonNull List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertFalse("ID " + s.getId(), s.hasKeyFieldsOnly());
+        }
+        return actualShortcuts;
+    }
+
+    @NonNull
     private List<ShortcutInfo> assertAllDynamic(@NonNull List<ShortcutInfo> actualShortcuts) {
         return assertAllHaveFlags(actualShortcuts, ShortcutInfo.FLAG_DYNAMIC);
     }
@@ -488,6 +794,47 @@
         return actualShortcuts;
     }
 
+    private void assertBitmapSize(int expectedWidth, int expectedHeight, @NonNull Bitmap bitmap) {
+        assertEquals("width", expectedWidth, bitmap.getWidth());
+        assertEquals("height", expectedHeight, bitmap.getHeight());
+    }
+
+    private <T> void assertAllUnique(Collection<T> list) {
+        final Set<Object> set = new HashSet<>();
+        for (T item : list) {
+            if (set.contains(item)) {
+                fail("Duplicate item found: " + item + " (in the list: " + list + ")");
+            }
+            set.add(item);
+        }
+    }
+
+    @NonNull
+    private Bitmap pfdToBitmap(@NonNull ParcelFileDescriptor pfd) {
+        Preconditions.checkNotNull(pfd);
+        try {
+            return BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
+        } finally {
+            IoUtils.closeQuietly(pfd);
+        }
+    }
+
+    private void assertBundleEmpty(BaseBundle b) {
+        assertTrue(b == null || b.size() == 0);
+    }
+
+    private ShortcutInfo getPackageShortcut(String packageName, String shortcutId, int userId) {
+        return mService.getPackageShortcutForTest(packageName, shortcutId, userId);
+    }
+
+    private ShortcutInfo getPackageShortcut(String packageName, String shortcutId) {
+        return getPackageShortcut(packageName, shortcutId, getCallingUserId());
+    }
+
+    private ShortcutInfo getCallerShortcut(String shortcutId) {
+        return getPackageShortcut(getCallingPackage(), shortcutId, getCallingUserId());
+    }
+
     /**
      * Test for the first launch path, no settings file available.
      */
@@ -549,6 +896,44 @@
         // TODO Add various broken cases.
     }
 
+    public void testLoadConfig() {
+        mService.updateConfigurationLocked(
+                ConfigConstants.KEY_RESET_INTERVAL_SEC + "=123,"
+                        + ConfigConstants.KEY_MAX_SHORTCUTS + "=4,"
+                        + ConfigConstants.KEY_MAX_DAILY_UPDATES + "=5,"
+                        + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=100,"
+                        + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "=50,"
+                        + ConfigConstants.KEY_ICON_FORMAT + "=WEBP,"
+                        + ConfigConstants.KEY_ICON_QUALITY + "=75");
+        assertEquals(123000, mService.getResetIntervalForTest());
+        assertEquals(4, mService.getMaxDynamicShortcutsForTest());
+        assertEquals(5, mService.getMaxDailyUpdatesForTest());
+        assertEquals(100, mService.getMaxIconDimensionForTest());
+        assertEquals(CompressFormat.WEBP, mService.getIconPersistFormatForTest());
+        assertEquals(75, mService.getIconPersistQualityForTest());
+
+        mInjectdIsLowRamDevice = true;
+        mService.updateConfigurationLocked(
+                ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=100,"
+                        + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "=50,"
+                        + ConfigConstants.KEY_ICON_FORMAT + "=JPEG");
+        assertEquals(ShortcutService.DEFAULT_RESET_INTERVAL_SEC * 1000,
+                mService.getResetIntervalForTest());
+
+        assertEquals(ShortcutService.DEFAULT_MAX_SHORTCUTS_PER_APP,
+                mService.getMaxDynamicShortcutsForTest());
+
+        assertEquals(ShortcutService.DEFAULT_MAX_DAILY_UPDATES,
+                mService.getMaxDailyUpdatesForTest());
+
+        assertEquals(50, mService.getMaxIconDimensionForTest());
+
+        assertEquals(CompressFormat.JPEG, mService.getIconPersistFormatForTest());
+
+        assertEquals(ShortcutService.DEFAULT_ICON_PERSIST_QUALITY,
+                mService.getIconPersistQualityForTest());
+    }
+
     // === Test for app side APIs ===
 
     /** Test for {@link android.content.pm.ShortcutManager#getMaxDynamicShortcutCount()} */
@@ -571,9 +956,9 @@
     }
 
     public void testSetDynamicShortcuts() {
-        final Icon icon1 = Icon.createWithResource(mContext, R.drawable.icon1);
+        final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.icon1);
         final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
-                mContext.getResources(), R.drawable.icon2));
+                getTestContext().getResources(), R.drawable.icon2));
 
         final ShortcutInfo si1 = makeShortcut(
                 "shortcut1",
@@ -594,13 +979,17 @@
         final ShortcutInfo si3 = makeShortcut("shortcut3");
 
         assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2)));
-        assertEquals(2, mManager.getDynamicShortcuts().size());
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut1", "shortcut2");
         assertEquals(2, mManager.getRemainingCallCount());
 
         // TODO: Check fields
 
         assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
-        assertEquals(1, mManager.getDynamicShortcuts().size());
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut1");
         assertEquals(1, mManager.getRemainingCallCount());
 
         assertTrue(mManager.setDynamicShortcuts(Arrays.asList()));
@@ -610,7 +999,7 @@
         dumpsysOnLogcat();
 
         mInjectedCurrentTimeLillis++; // Need to advance the clock for reset to work.
-        mService.resetThrottlingInner();
+        mService.resetThrottlingInner(UserHandle.USER_SYSTEM);
 
         dumpsysOnLogcat();
 
@@ -629,16 +1018,22 @@
 
         assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
         assertEquals(2, mManager.getRemainingCallCount());
-        assertEquals(1, mManager.getDynamicShortcuts().size());
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut1");
 
         assertTrue(mManager.addDynamicShortcut(si2));
         assertEquals(1, mManager.getRemainingCallCount());
-        assertEquals(2, mManager.getDynamicShortcuts().size());
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut1", "shortcut2");
 
         // Add with the same ID
         assertTrue(mManager.addDynamicShortcut(makeShortcut("shortcut1")));
         assertEquals(0, mManager.getRemainingCallCount());
-        assertEquals(2, mManager.getDynamicShortcuts().size()); // Still 2
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut1", "shortcut2");
 
         // TODO Check max number
 
@@ -651,24 +1046,35 @@
         final ShortcutInfo si3 = makeShortcut("shortcut3");
 
         assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2, si3)));
-        assertEquals(3, mManager.getDynamicShortcuts().size());
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut1", "shortcut2", "shortcut3");
 
         assertEquals(2, mManager.getRemainingCallCount());
 
         mManager.deleteDynamicShortcut("shortcut1");
-        assertEquals(2, mManager.getDynamicShortcuts().size());
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut2", "shortcut3");
 
         mManager.deleteDynamicShortcut("shortcut1");
-        assertEquals(2, mManager.getDynamicShortcuts().size());
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut2", "shortcut3");
 
         mManager.deleteDynamicShortcut("shortcutXXX");
-        assertEquals(2, mManager.getDynamicShortcuts().size());
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut2", "shortcut3");
 
         mManager.deleteDynamicShortcut("shortcut2");
-        assertEquals(1, mManager.getDynamicShortcuts().size());
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut3");
 
         mManager.deleteDynamicShortcut("shortcut3");
-        assertEquals(0, mManager.getDynamicShortcuts().size());
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()));
 
         // Still 2 calls left.
         assertEquals(2, mManager.getRemainingCallCount());
@@ -682,7 +1088,9 @@
         final ShortcutInfo si3 = makeShortcut("shortcut3");
 
         assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2, si3)));
-        assertEquals(3, mManager.getDynamicShortcuts().size());
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mManager.getDynamicShortcuts()),
+                "shortcut1", "shortcut2", "shortcut3");
 
         assertEquals(2, mManager.getRemainingCallCount());
 
@@ -732,7 +1140,7 @@
 
         // Now it should work.
         mInjectedCurrentTimeLillis++;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1))); // fail
         assertEquals(2, mManager.getRemainingCallCount());
 
         mInjectedCurrentTimeLillis++;
@@ -831,11 +1239,363 @@
         assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si2)));
     }
 
+    public void testIcons() {
+        final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
+        final Icon res64x64 = Icon.createWithResource(getTestContext(), R.drawable.black_64x64);
+        final Icon res512x512 = Icon.createWithResource(getTestContext(), R.drawable.black_512x512);
+
+        final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                getTestContext().getResources(), R.drawable.black_32x32));
+        final Icon bmp64x64 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                getTestContext().getResources(), R.drawable.black_64x64));
+        final Icon bmp512x512 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                getTestContext().getResources(), R.drawable.black_512x512));
+
+        // Set from package 1
+        setCaller(CALLING_PACKAGE_1);
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                makeShortcutWithIcon("res32x32", res32x32),
+                makeShortcutWithIcon("res64x64", res64x64),
+                makeShortcutWithIcon("bmp32x32", bmp32x32),
+                makeShortcutWithIcon("bmp64x64", bmp64x64),
+                makeShortcutWithIcon("bmp512x512", bmp512x512),
+                makeShortcut("none")
+        )));
+
+        // getDynamicShortcuts() shouldn't return icons, thus assertAllNotHaveIcon().
+        assertShortcutIds(assertAllNotHaveIcon(mManager.getDynamicShortcuts()),
+                "res32x32",
+                "res64x64",
+                "bmp32x32",
+                "bmp64x64",
+                "bmp512x512",
+                "none");
+
+        // Call from another caller with the same ID, just to make sure storage is per-package.
+        setCaller(CALLING_PACKAGE_2);
+        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                makeShortcutWithIcon("res32x32", res512x512),
+                makeShortcutWithIcon("res64x64", res512x512),
+                makeShortcutWithIcon("none", res512x512)
+        )));
+        assertShortcutIds(assertAllNotHaveIcon(mManager.getDynamicShortcuts()),
+                "res32x32",
+                "res64x64",
+                "none");
+
+        // Re-initialize and load from the files.
+        initService();
+
+        // Load from launcher.
+        Bitmap bmp;
+
+        setCaller(LAUNCHER_1);
+
+        // Check hasIconResource()/hasIconFile().
+        assertShortcutIds(assertAllHaveIconResId(mLauncherApps.getShortcutInfo(
+                CALLING_PACKAGE_1, Arrays.asList("res32x32"),
+                getCallingUser())), "res32x32");
+
+        assertShortcutIds(assertAllHaveIconResId(mLauncherApps.getShortcutInfo(
+                CALLING_PACKAGE_1, Arrays.asList("res64x64"), getCallingUser())),
+                "res64x64");
+
+        assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
+                CALLING_PACKAGE_1, Arrays.asList("bmp32x32"), getCallingUser())),
+                "bmp32x32");
+
+        assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
+                CALLING_PACKAGE_1, Arrays.asList("bmp64x64"), getCallingUser())),
+                "bmp64x64");
+
+        assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
+                CALLING_PACKAGE_1, Arrays.asList("bmp512x512"), getCallingUser())),
+                "bmp512x512");
+
+        // Check
+        assertEquals(
+                R.drawable.black_32x32,
+                mLauncherApps.getShortcutIconResId(
+                        makePackageShortcut(CALLING_PACKAGE_1, "res32x32"), getCallingUser()));
+
+        assertEquals(
+                R.drawable.black_64x64,
+                mLauncherApps.getShortcutIconResId(
+
+                        makePackageShortcut(CALLING_PACKAGE_1, "res64x64"), getCallingUser()));
+
+        assertEquals(
+                0, // because it's not a resource
+                mLauncherApps.getShortcutIconResId(
+                        makePackageShortcut(CALLING_PACKAGE_1, "bmp32x32"), getCallingUser()));
+        assertEquals(
+                0, // because it's not a resource
+                mLauncherApps.getShortcutIconResId(
+                        makePackageShortcut(CALLING_PACKAGE_1, "bmp64x64"), getCallingUser()));
+        assertEquals(
+                0, // because it's not a resource
+                mLauncherApps.getShortcutIconResId(
+                        makePackageShortcut(CALLING_PACKAGE_1, "bmp512x512"), getCallingUser()));
+
+        bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
+                makePackageShortcut(CALLING_PACKAGE_1, "bmp32x32"), getCallingUser()));
+        assertBitmapSize(32, 32, bmp);
+
+        bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
+                makePackageShortcut(CALLING_PACKAGE_1, "bmp64x64"), getCallingUser()));
+        assertBitmapSize(64, 64, bmp);
+
+        bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
+                makePackageShortcut(CALLING_PACKAGE_1, "bmp512x512"), getCallingUser()));
+        assertBitmapSize(128, 128, bmp);
+
+        // TODO Test the content URI case too.
+    }
+
+    private void checkShrinkBitmap(int expectedWidth, int expectedHeight, int resId, int maxSize) {
+        assertBitmapSize(expectedWidth, expectedHeight,
+                ShortcutService.shrinkBitmap(BitmapFactory.decodeResource(
+                        getTestContext().getResources(), resId),
+                        maxSize));
+    }
+
+    public void testShrinkBitmap() {
+        checkShrinkBitmap(32, 32, R.drawable.black_512x512, 32);
+        checkShrinkBitmap(511, 511, R.drawable.black_512x512, 511);
+        checkShrinkBitmap(512, 512, R.drawable.black_512x512, 512);
+
+        checkShrinkBitmap(1024, 4096, R.drawable.black_1024x4096, 4096);
+        checkShrinkBitmap(1024, 4096, R.drawable.black_1024x4096, 4100);
+        checkShrinkBitmap(512, 2048, R.drawable.black_1024x4096, 2048);
+
+        checkShrinkBitmap(4096, 1024, R.drawable.black_4096x1024, 4096);
+        checkShrinkBitmap(4096, 1024, R.drawable.black_4096x1024, 4100);
+        checkShrinkBitmap(2048, 512, R.drawable.black_4096x1024, 2048);
+    }
+
+    private File openIconFileForWriteAndGetPath(int userId, String packageName)
+            throws IOException {
+        // Shortcut IDs aren't used in the path, so just pass the same ID.
+        final FileOutputStreamWithPath out =
+                mService.openIconFileForWrite(userId, makePackageShortcut(packageName, "id"));
+        out.close();
+        return out.getFile();
+    }
+
+    public void testOpenIconFileForWrite() throws IOException {
+        mInjectedCurrentTimeLillis = 1000;
+
+        final File p10_1_1 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
+        final File p10_1_2 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
+
+        final File p10_2_1 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_2);
+        final File p10_2_2 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_2);
+
+        final File p11_1_1 = openIconFileForWriteAndGetPath(11, CALLING_PACKAGE_1);
+        final File p11_1_2 = openIconFileForWriteAndGetPath(11, CALLING_PACKAGE_1);
+
+        mInjectedCurrentTimeLillis++;
+
+        final File p10_1_3 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
+        final File p10_1_4 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
+        final File p10_1_5 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_1);
+
+        final File p10_2_3 = openIconFileForWriteAndGetPath(10, CALLING_PACKAGE_2);
+        final File p11_1_3 = openIconFileForWriteAndGetPath(11, CALLING_PACKAGE_1);
+
+        // Make sure their paths are all unique
+        assertAllUnique(Arrays.asList(
+                p10_1_1,
+                p10_1_2,
+                p10_1_3,
+                p10_1_4,
+                p10_1_5,
+
+                p10_2_1,
+                p10_2_2,
+                p10_2_3,
+
+                p11_1_1,
+                p11_1_2,
+                p11_1_3
+        ));
+
+        // Check each set has the same parent.
+        assertEquals(p10_1_1.getParent(), p10_1_2.getParent());
+        assertEquals(p10_1_1.getParent(), p10_1_3.getParent());
+        assertEquals(p10_1_1.getParent(), p10_1_4.getParent());
+        assertEquals(p10_1_1.getParent(), p10_1_5.getParent());
+
+        assertEquals(p10_2_1.getParent(), p10_2_2.getParent());
+        assertEquals(p10_2_1.getParent(), p10_2_3.getParent());
+
+        assertEquals(p11_1_1.getParent(), p11_1_2.getParent());
+        assertEquals(p11_1_1.getParent(), p11_1_3.getParent());
+
+        // Check the parents are still unique.
+        assertAllUnique(Arrays.asList(
+                p10_1_1.getParent(),
+                p10_2_1.getParent(),
+                p11_1_1.getParent()
+        ));
+
+        // All files created at the same time for the same package/user, expcet for the first ones,
+        // will have "_" in the path.
+        assertFalse(p10_1_1.getName().contains("_"));
+        assertTrue(p10_1_2.getName().contains("_"));
+        assertFalse(p10_1_3.getName().contains("_"));
+        assertTrue(p10_1_4.getName().contains("_"));
+        assertTrue(p10_1_5.getName().contains("_"));
+
+        assertFalse(p10_2_1.getName().contains("_"));
+        assertTrue(p10_2_2.getName().contains("_"));
+        assertFalse(p10_2_3.getName().contains("_"));
+
+        assertFalse(p11_1_1.getName().contains("_"));
+        assertTrue(p11_1_2.getName().contains("_"));
+        assertFalse(p11_1_3.getName().contains("_"));
+    }
+
+    public void testUpdateShortcuts() {
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                    makeShortcut("s1"),
+                    makeShortcut("s2"),
+                    makeShortcut("s3"),
+                    makeShortcut("s4"),
+                    makeShortcut("s5")
+            )));
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                    makeShortcut("s1"),
+                    makeShortcut("s2"),
+                    makeShortcut("s3"),
+                    makeShortcut("s4"),
+                    makeShortcut("s5")
+            )));
+        });
+        runWithCaller(LAUNCHER_1, UserHandle.USER_SYSTEM, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s2", "s3"),
+                    getCallingUser());
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList("s4", "s5"),
+                    getCallingUser());
+        });
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            mManager.deleteDynamicShortcut("s1");
+            mManager.deleteDynamicShortcut("s2");
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            mManager.deleteDynamicShortcut("s1");
+            mManager.deleteDynamicShortcut("s3");
+            mManager.deleteDynamicShortcut("s5");
+        });
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertShortcutIds(assertAllDynamic(
+                    mManager.getDynamicShortcuts()),
+                    "s3", "s4", "s5");
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s2", "s3");
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            assertShortcutIds(assertAllDynamic(
+                    mManager.getDynamicShortcuts()),
+                    "s2", "s4");
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s4", "s5");
+        });
+
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            ShortcutInfo s2 = makeShortcutBuilder()
+                    .setId("s2")
+                    .setIcon(Icon.createWithResource(getTestContext(), R.drawable.black_32x32))
+                    .build();
+
+            ShortcutInfo s4 = makeShortcutBuilder()
+                    .setId("s4")
+                    .setTitle("new title")
+                    .build();
+
+            mManager.updateShortcuts(Arrays.asList(s2, s4));
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            ShortcutInfo s2 = makeShortcutBuilder()
+                    .setId("s2")
+                    .setIntent(makeIntent(Intent.ACTION_ANSWER, ShortcutActivity.class,
+                            "key1", "val1"))
+                    .build();
+
+            ShortcutInfo s4 = makeShortcutBuilder()
+                    .setId("s4")
+                    .setIntent(new Intent(Intent.ACTION_ALL_APPS))
+                    .build();
+
+            mManager.updateShortcuts(Arrays.asList(s2, s4));
+        });
+
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertShortcutIds(assertAllDynamic(
+                    mManager.getDynamicShortcuts()),
+                    "s3", "s4", "s5");
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s2", "s3");
+
+            ShortcutInfo s = getCallerShortcut("s2");
+            assertTrue(s.hasIconResource());
+            assertEquals(R.drawable.black_32x32, s.getIconResourceId());
+            assertEquals("Title-s2", s.getTitle());
+
+            s = getCallerShortcut("s4");
+            assertFalse(s.hasIconResource());
+            assertEquals(0, s.getIconResourceId());
+            assertEquals("new title", s.getTitle());
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            assertShortcutIds(assertAllDynamic(
+                    mManager.getDynamicShortcuts()),
+                    "s2", "s4");
+            assertShortcutIds(assertAllPinned(
+                    mManager.getPinnedShortcuts()),
+                    "s4", "s5");
+
+            ShortcutInfo s = getCallerShortcut("s2");
+            assertFalse(s.hasIconResource());
+            assertEquals(0, s.getIconResourceId());
+            assertEquals("Title-s2", s.getTitle());
+            assertEquals(Intent.ACTION_ANSWER, s.getIntent().getAction());
+            assertEquals(1, s.getIntent().getExtras().size());
+
+            s = getCallerShortcut("s4");
+            assertFalse(s.hasIconResource());
+            assertEquals(0, s.getIconResourceId());
+            assertEquals("Title-s4", s.getTitle());
+            assertEquals(Intent.ACTION_ALL_APPS, s.getIntent().getAction());
+            assertBundleEmpty(s.getIntent().getExtras());
+        });
+        // TODO Check with other fields too.
+
+        // TODO Check bitmap removal too.
+    }
+
     // TODO: updateShortcuts()
     // TODO: getPinnedShortcuts()
 
     // === Test for launcher side APIs ===
 
+    private static ShortcutQuery buildQuery(long changedSince,
+            String packageName, ComponentName componentName,
+            /* @ShortcutQuery.QueryFlags */ int flags) {
+        final ShortcutQuery q = new ShortcutQuery();
+        q.setChangedSince(changedSince);
+        q.setPackage(packageName);
+        q.setActivity(componentName);
+        q.setQueryFlags(flags);
+        return q;
+    }
+
     public void testGetShortcuts() {
 
         // Set up shortcuts.
@@ -860,53 +1620,56 @@
 
         // Get dynamic
         assertAllDynamic(assertAllHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
-                mInternal.getShortcuts(getCallingPackage(), /* time =*/ 0, CALLING_PACKAGE_1,
-                        /* activity =*/ null,
-                    ShortcutQuery.FLAG_GET_DYNAMIC, getCallingUserId()),
+                assertAllNotKeyFieldsOnly(
+                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                        /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())),
                 "s1", "s2"))));
 
         // Get pinned
         assertShortcutIds(
-                mInternal.getShortcuts(getCallingPackage(),  /* time =*/ 0, CALLING_PACKAGE_1,
+                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
                         /* activity =*/ null,
-                        ShortcutQuery.FLAG_GET_PINNED, getCallingUserId())
+                        ShortcutQuery.FLAG_GET_PINNED), getCallingUser())
                 /* none */);
 
         // Get both, with timestamp
         assertAllDynamic(assertAllHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
-                mInternal.getShortcuts(getCallingPackage(),  /* time =*/ 1000, CALLING_PACKAGE_2,
+                assertAllNotKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+                        /* time =*/ 1000, CALLING_PACKAGE_2,
                         /* activity =*/ null,
-                        ShortcutQuery.FLAG_GET_PINNED | ShortcutQuery.FLAG_GET_DYNAMIC,
-                        getCallingUserId()),
+                        ShortcutQuery.FLAG_GET_PINNED | ShortcutQuery.FLAG_GET_DYNAMIC),
+                        getCallingUser())),
                 "s2", "s3"))));
 
         // FLAG_GET_KEY_FIELDS_ONLY
         assertAllDynamic(assertAllNotHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
-                mInternal.getShortcuts(getCallingPackage(), /* time =*/ 1000, CALLING_PACKAGE_2,
+                assertAllKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+                        /* time =*/ 1000, CALLING_PACKAGE_2,
                         /* activity =*/ null,
-                        ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY,
-                        getCallingUserId()),
+                        ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY),
+                        getCallingUser())),
                 "s2", "s3"))));
 
         // Pin some shortcuts.
-        mInternal.pinShortcuts(getCallingPackage(), CALLING_PACKAGE_2,
-                Arrays.asList("s3", "s4"), getCallingUserId());
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                Arrays.asList("s3", "s4"), getCallingUser());
 
         // Pinned ones only
         assertAllPinned(assertAllHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
-                mInternal.getShortcuts(getCallingPackage(), /* time =*/ 1000, CALLING_PACKAGE_2,
+                assertAllNotKeyFieldsOnly(mLauncherApps.getShortcuts(buildQuery(
+                        /* time =*/ 1000, CALLING_PACKAGE_2,
                         /* activity =*/ null,
-                        ShortcutQuery.FLAG_GET_PINNED,
-                        getCallingUserId()),
+                        ShortcutQuery.FLAG_GET_PINNED),
+                        getCallingUser())),
                 "s3"))));
 
         // All packages.
-        assertShortcutIds(
-                mInternal.getShortcuts(getCallingPackage(),
+        assertShortcutIds(assertAllNotKeyFieldsOnly(
+                mLauncherApps.getShortcuts(buildQuery(
                         /* time =*/ 5000, /* package= */ null,
                         /* activity =*/ null,
-                        ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED,
-                        getCallingUserId()),
+                        ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED),
+                        getCallingUser())),
                 "s1", "s3");
 
         // TODO More tests: pinned but dynamic, filter by activity
@@ -950,8 +1713,8 @@
         // Pin some.
         setCaller(LAUNCHER_1);
 
-        mInternal.pinShortcuts(getCallingPackage(), CALLING_PACKAGE_1,
-                Arrays.asList("s2"), getCallingUserId());
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                Arrays.asList("s2"), getCallingUser());
 
         dumpsysOnLogcat();
 
@@ -968,20 +1731,21 @@
 
         // Note we don't guarantee the orders.
         list = assertShortcutIds(assertAllHaveTitle(assertAllNotHaveIntents(
-                mInternal.getShortcutInfo(getCallingPackage(), CALLING_PACKAGE_1,
-                Arrays.asList("s2", "s1", "s3", null), getCallingUserId()))),
+                assertAllNotKeyFieldsOnly(
+                mLauncherApps.getShortcutInfo(CALLING_PACKAGE_1,
+                Arrays.asList("s2", "s1", "s3", null), getCallingUser())))),
                 "s1", "s2");
         assertEquals("Title 1", findById(list, "s1").getTitle());
         assertEquals("Title 2", findById(list, "s2").getTitle());
 
         assertShortcutIds(assertAllHaveTitle(assertAllNotHaveIntents(
-                mInternal.getShortcutInfo(getCallingPackage(), CALLING_PACKAGE_1,
-                        Arrays.asList("s3"), getCallingUserId())))
+                mLauncherApps.getShortcutInfo(CALLING_PACKAGE_1,
+                        Arrays.asList("s3"), getCallingUser())))
                 /* none */);
 
         list = assertShortcutIds(assertAllHaveTitle(assertAllNotHaveIntents(
-                mInternal.getShortcutInfo(getCallingPackage(), CALLING_PACKAGE_2,
-                        Arrays.asList("s1", "s2", "s3"), getCallingUserId()))),
+                mLauncherApps.getShortcutInfo(CALLING_PACKAGE_2,
+                        Arrays.asList("s1", "s2", "s3"), getCallingUser()))),
                 "s1");
         assertEquals("ABC", findById(list, "s1").getTitle());
     }
@@ -1007,14 +1771,14 @@
         // Pin some.
         setCaller(LAUNCHER_1);
 
-        mInternal.pinShortcuts(getCallingPackage(), CALLING_PACKAGE_1,
-                Arrays.asList("s2", "s3"), getCallingUserId());
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                Arrays.asList("s2", "s3"), getCallingUser());
 
-        mInternal.pinShortcuts(getCallingPackage(), CALLING_PACKAGE_2,
-                Arrays.asList("s3", "s4", "s5"), getCallingUserId());
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                Arrays.asList("s3", "s4", "s5"), getCallingUser());
 
-        mInternal.pinShortcuts(getCallingPackage(), CALLING_PACKAGE_3,
-                Arrays.asList("s3"), getCallingUserId());  // Note ID doesn't exist
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_3,
+                Arrays.asList("s3"), getCallingUser());  // Note ID doesn't exist
 
         // Delete some.
         setCaller(CALLING_PACKAGE_1);
@@ -1036,19 +1800,19 @@
         setCaller(LAUNCHER_1);
 
         // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists.
-        assertShortcutIds(assertAllPinned(
-                mInternal.getShortcuts(getCallingPackage(), /* time =*/ 0, CALLING_PACKAGE_1,
-                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED, getCallingUserId())),
+        assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
                 "s2");
 
-        assertShortcutIds(assertAllPinned(
-                mInternal.getShortcuts(getCallingPackage(), /* time =*/ 0, CALLING_PACKAGE_2,
-                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED, getCallingUserId())),
+        assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
                 "s3", "s4");
 
-        assertShortcutIds(assertAllPinned(
-                mInternal.getShortcuts(getCallingPackage(), /* time =*/ 0, CALLING_PACKAGE_3,
-                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED, getCallingUserId()))
+        assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
+                mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_3,
+                /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))
                 /* none */);
     }
 
@@ -1087,11 +1851,11 @@
 
         // Pin all.
         setCaller(LAUNCHER_1);
-        mInternal.pinShortcuts(getCallingPackage(), CALLING_PACKAGE_1,
-                Arrays.asList("s1", "s2"), getCallingUserId());
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                Arrays.asList("s1", "s2"), getCallingUser());
 
-        mInternal.pinShortcuts(getCallingPackage(), CALLING_PACKAGE_2,
-                Arrays.asList("s1"), getCallingUserId());
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                Arrays.asList("s1"), getCallingUser());
 
         // Just to make it complicated, delete some.
         setCaller(CALLING_PACKAGE_1);
@@ -1115,6 +1879,125 @@
         // TODO Check extra, etc
     }
 
+    public void testLauncherCallback() throws Throwable {
+        LauncherApps.Callback c0 = mock(LauncherApps.Callback.class);
+
+
+        // Set listeners
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.registerCallback(c0, new Handler(Looper.getMainLooper()));
+        });
+
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+
+        waitOnMainThread();
+        ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
+        verify(c0).onShortcutsChanged(
+                eq(CALLING_PACKAGE_1),
+                shortcuts.capture(),
+                eq(UserHandle.of(USER_0))
+        );
+        assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
+                "s1", "s2", "s3");
+
+        // From different package.
+        reset(c0);
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+        waitOnMainThread();
+        shortcuts = ArgumentCaptor.forClass(List.class);
+        verify(c0).onShortcutsChanged(
+                eq(CALLING_PACKAGE_2),
+                shortcuts.capture(),
+                eq(UserHandle.of(USER_0))
+        );
+        assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
+                "s1", "s2", "s3");
+
+        // Different user, callback shouldn't be called.
+        reset(c0);
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+        waitOnMainThread();
+        verify(c0, times(0)).onShortcutsChanged(
+                anyString(),
+                any(List.class),
+                any(UserHandle.class)
+        );
+
+        // Test for addDynamicShortcut.
+        reset(c0);
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertTrue(mManager.addDynamicShortcut(makeShortcut("s4")));
+        });
+
+        waitOnMainThread();
+        shortcuts = ArgumentCaptor.forClass(List.class);
+        verify(c0).onShortcutsChanged(
+                eq(CALLING_PACKAGE_1),
+                shortcuts.capture(),
+                eq(UserHandle.of(USER_0))
+        );
+        assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
+                "s1", "s2", "s3", "s4");
+
+        // Test for remove
+        reset(c0);
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            mManager.deleteDynamicShortcut("s1");
+        });
+
+        waitOnMainThread();
+        shortcuts = ArgumentCaptor.forClass(List.class);
+        verify(c0).onShortcutsChanged(
+                eq(CALLING_PACKAGE_1),
+                shortcuts.capture(),
+                eq(UserHandle.of(USER_0))
+        );
+        assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
+                "s2", "s3", "s4");
+
+        // Test for update
+        reset(c0);
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertTrue(mManager.updateShortcuts(Arrays.asList(
+                    makeShortcut("s1"), makeShortcut("s2"))));
+        });
+
+        waitOnMainThread();
+        shortcuts = ArgumentCaptor.forClass(List.class);
+        verify(c0).onShortcutsChanged(
+                eq(CALLING_PACKAGE_1),
+                shortcuts.capture(),
+                eq(UserHandle.of(USER_0))
+        );
+        assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
+                "s2", "s3", "s4");
+
+        // Test for deleteAll
+        reset(c0);
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            mManager.deleteAllDynamicShortcuts();
+        });
+
+        waitOnMainThread();
+        shortcuts = ArgumentCaptor.forClass(List.class);
+        verify(c0).onShortcutsChanged(
+                eq(CALLING_PACKAGE_1),
+                shortcuts.capture(),
+                eq(UserHandle.of(USER_0))
+        );
+        assertEquals(0, shortcuts.getValue().size());
+    }
+
     // === Test for persisting ===
 
     public void testSaveAndLoadUser_empty() {
@@ -1135,35 +2018,90 @@
      */
     public void testSaveAndLoadUser() {
         // First, create some shortcuts and save.
-        final Icon icon1 = Icon.createWithResource(mContext, R.drawable.icon1);
-        final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
-                mContext.getResources(), R.drawable.icon2));
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_64x16);
+            final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                    getTestContext().getResources(), R.drawable.icon2));
 
-        final ShortcutInfo si1 = makeShortcut(
-                "shortcut1",
-                "Title 1",
-                makeComponent(ShortcutActivity.class),
-                icon1,
-                makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
-                        "key1", "val1", "nest", makeBundle("key", 123)),
-                /* weight */ 10);
+            final ShortcutInfo si1 = makeShortcut(
+                    "s1",
+                    "title1-1",
+                    makeComponent(ShortcutActivity.class),
+                    icon1,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+                            "key1", "val1", "nest", makeBundle("key", 123)),
+                        /* weight */ 10);
 
-        final ShortcutInfo si2 = makeShortcut(
-                "shortcut2",
-                "Title 2",
-                /* activity */ null,
-                icon2,
-                makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-                /* weight */ 12);
+            final ShortcutInfo si2 = makeShortcut(
+                    "s2",
+                    "title1-2",
+                        /* activity */ null,
+                    icon2,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+                        /* weight */ 12);
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2)));
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2)));
 
-        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
-        assertEquals(2, mManager.getRemainingCallCount());
+            assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+            assertEquals(2, mManager.getRemainingCallCount());
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_16x64);
+            final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                    getTestContext().getResources(), R.drawable.icon2));
 
-        Log.i(TAG, "Saved state");
-        dumpsysOnLogcat();
-        dumpUserFile(0);
+            final ShortcutInfo si1 = makeShortcut(
+                    "s1",
+                    "title2-1",
+                    makeComponent(ShortcutActivity.class),
+                    icon1,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+                            "key1", "val1", "nest", makeBundle("key", 123)),
+                        /* weight */ 10);
+
+            final ShortcutInfo si2 = makeShortcut(
+                    "s2",
+                    "title2-2",
+                        /* activity */ null,
+                    icon2,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+                        /* weight */ 12);
+
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2)));
+
+            assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+            assertEquals(2, mManager.getRemainingCallCount());
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_64x64);
+            final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                    getTestContext().getResources(), R.drawable.icon2));
+
+            final ShortcutInfo si1 = makeShortcut(
+                    "s1",
+                    "title10-1-1",
+                    makeComponent(ShortcutActivity.class),
+                    icon1,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+                            "key1", "val1", "nest", makeBundle("key", 123)),
+                        /* weight */ 10);
+
+            final ShortcutInfo si2 = makeShortcut(
+                    "s2",
+                    "title10-1-2",
+                        /* activity */ null,
+                    icon2,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+                        /* weight */ 12);
+
+            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2)));
+
+            assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+            assertEquals(2, mManager.getRemainingCallCount());
+        });
+
+        mService.getShortcutsForTest().get(UserHandle.USER_SYSTEM).setLauncherComponent(
+                mService, new ComponentName("pkg1", "class"));
 
         // Restore.
         initService();
@@ -1177,30 +2115,52 @@
         // Now it's loaded.
         assertEquals(1, mService.getShortcutsForTest().size());
 
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
+                    mManager.getDynamicShortcuts()))), "s1", "s2");
+            assertEquals(2, mManager.getRemainingCallCount());
+
+            assertEquals("title1-1", getCallerShortcut("s1").getTitle());
+            assertEquals("title1-2", getCallerShortcut("s2").getTitle());
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
+                    mManager.getDynamicShortcuts()))), "s1", "s2");
+            assertEquals(2, mManager.getRemainingCallCount());
+
+            assertEquals("title2-1", getCallerShortcut("s1").getTitle());
+            assertEquals("title2-2", getCallerShortcut("s2").getTitle());
+        });
+
+        assertEquals("pkg1", mService.getShortcutsForTest().get(UserHandle.USER_SYSTEM)
+                .getLauncherComponent().getPackageName());
+
         // Start another user
-        mService.onStartUserLocked(10);
+        mService.onStartUserLocked(USER_10);
 
         // Now the size is 2.
         assertEquals(2, mService.getShortcutsForTest().size());
 
-        Log.i(TAG, "Dumping the new instance");
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
+                    mManager.getDynamicShortcuts()))), "s1", "s2");
+            assertEquals(2, mManager.getRemainingCallCount());
 
-        List<ShortcutInfo> loaded = mManager.getDynamicShortcuts();
-
-        Log.i(TAG, "Loaded state");
-        dumpsysOnLogcat();
-
-        assertEquals(2, loaded.size());
-
-        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
-        assertEquals(2, mManager.getRemainingCallCount());
+            assertEquals("title10-1-1", getCallerShortcut("s1").getTitle());
+            assertEquals("title10-1-2", getCallerShortcut("s2").getTitle());
+        });
+        assertNull(mService.getShortcutsForTest().get(USER_10).getLauncherComponent());
 
         // Try stopping the user
-        mService.onCleanupUserInner(UserHandle.USER_SYSTEM);
+        mService.onCleanupUserInner(USER_10);
 
         // Now it's unloaded.
         assertEquals(1, mService.getShortcutsForTest().size());
 
         // TODO Check all other fields
     }
+
+    // TODO Detailed test for hasShortcutPermissionInner().
+
+    // TODO Add tests for the command line functions too.
 }
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index 3e2b43d..a3313c9 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -274,6 +274,11 @@
                 - (idle ? mScreenOnTimeThreshold : 0) - 1000 /* just a second more */;
     }
 
+    public void clearUsageLocked(String packageName, int userId) {
+        ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId);
+        userHistory.remove(packageName);
+    }
+
     private boolean hasPassedThresholdsLocked(PackageHistory packageHistory, long elapsedRealtime) {
         return (packageHistory.lastUsedScreenTime
                     <= getScreenOnTimeLocked(elapsedRealtime) - mScreenOnTimeThreshold)
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 8da1785..beec40f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -180,6 +180,7 @@
         IntentFilter packageFilter = new IntentFilter();
         packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
         packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+        packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         packageFilter.addDataScheme("package");
 
         getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL, packageFilter,
@@ -266,6 +267,12 @@
                     || Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
                 clearCarrierPrivilegedApps();
             }
+            if ((Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
+                    Intent.ACTION_PACKAGE_ADDED.equals(action))
+                    && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+                clearAppIdleForPackage(intent.getData().getSchemeSpecificPart(),
+                        getSendingUserId());
+            }
         }
     }
 
@@ -332,6 +339,12 @@
         }
     }
 
+    void clearAppIdleForPackage(String packageName, int userId) {
+        synchronized (mLock) {
+            mAppIdleHistory.clearUsageLocked(packageName, userId);
+        }
+    }
+
     private void cleanUpRemovedUsersLocked() {
         final List<UserInfo> users = mUserManager.getUsers(true);
         if (users == null || users.size() == 0) {
diff --git a/services/usb/java/com/android/server/usb/MtpNotificationManager.java b/services/usb/java/com/android/server/usb/MtpNotificationManager.java
index 17039bb..101e200 100644
--- a/services/usb/java/com/android/server/usb/MtpNotificationManager.java
+++ b/services/usb/java/com/android/server/usb/MtpNotificationManager.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
@@ -101,8 +102,8 @@
                 TAG, device.getDeviceId(), notification);
     }
 
-    void hideNotification(UsbDevice device) {
-        mContext.getSystemService(NotificationManager.class).cancel(TAG, device.getDeviceId());
+    void hideNotification(int deviceId) {
+        mContext.getSystemService(NotificationManager.class).cancel(TAG, deviceId);
     }
 
     private class Receiver extends BroadcastReceiver {
@@ -121,7 +122,13 @@
         }
     }
 
-    static boolean isMtpDevice(UsbDevice device) {
+    static boolean shouldShowNotification(PackageManager packageManager, UsbDevice device) {
+        // We don't show MTP notification for devices that has FEATURE_AUTOMOTIVE.
+        return !packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) &&
+                isMtpDevice(device);
+    }
+
+    private static boolean isMtpDevice(UsbDevice device) {
         for (int i = 0; i < device.getInterfaceCount(); i++) {
             final UsbInterface usbInterface = device.getInterface(i);
             if ((usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_STILL_IMAGE &&
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index c4d7336..de9ede3 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -738,7 +738,7 @@
         // Send broadcast to running activity with registered intent
         mUserContext.sendBroadcast(intent);
 
-        if (MtpNotificationManager.isMtpDevice(device)) {
+        if (MtpNotificationManager.shouldShowNotification(mPackageManager, device)) {
             // Show notification if the device is MTP storage.
             mMtpNotificationManager.showNotification(device);
         } else {
@@ -769,9 +769,7 @@
         if (DEBUG) Slog.d(TAG, "usbDeviceRemoved, sending " + intent);
         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
 
-        if (MtpNotificationManager.isMtpDevice(device)) {
-            mMtpNotificationManager.hideNotification(device);
-        }
+        mMtpNotificationManager.hideNotification(device.getDeviceId());
     }
 
     public void accessoryAttached(UsbAccessory accessory) {
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 10808da..afb7d93 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -95,6 +95,19 @@
     public static final int STATE_DISCONNECTING = 10;
 
     /**
+     * The state of an external call which is in the process of being pulled from a remote device to
+     * the local device.
+     * <p>
+     * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
+     * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
+     * <p>
+     * An {@link InCallService} will only see this state if it has the
+     * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
+     * manifest.
+     */
+    public static final int STATE_PULLING_CALL = 11;
+
+    /**
      * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
      * extras. Used to pass the phone accounts to display on the front end to the user in order to
      * select phone accounts to (for example) place a call.
@@ -226,8 +239,23 @@
          */
         public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
 
+        /**
+         * When set for an external call, indicates that this {@code Call} can be pulled from a
+         * remote device to the current device.
+         * <p>
+         * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
+         * <p>
+         * An {@link InCallService} will only see calls with this capability if it has the
+         * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
+         * in its manifest.
+         * <p>
+         * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
+         * {@link Connection#CAPABILITY_IS_EXTERNAL_CALL}.
+         */
+        public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
+
         //******************************************************************************************
-        // Next CAPABILITY value: 0x00800000
+        // Next CAPABILITY value: 0x01000000
         //******************************************************************************************
 
         /**
@@ -261,8 +289,25 @@
          */
         public static final int PROPERTY_WORK_CALL = 0x00000020;
 
+        /**
+         * When set, indicates that this {@code Call} does not actually exist locally for the
+         * {@link ConnectionService}.
+         * <p>
+         * Consider, for example, a scenario where a user has two phones with the same phone number.
+         * When a user places a call on one device, the telephony stack can represent that call on
+         * the other device by adding it to the {@link ConnectionService} with the
+         * {@link Connection#CAPABILITY_IS_EXTERNAL_CALL} capability set.
+         * <p>
+         * An {@link InCallService} will only see calls with this property if it has the
+         * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
+         * in its manifest.
+         * <p>
+         * See {@link Connection#CAPABILITY_IS_EXTERNAL_CALL}.
+         */
+        public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
+
         //******************************************************************************************
-        // Next PROPERTY value: 0x00000040
+        // Next PROPERTY value: 0x00000100
         //******************************************************************************************
 
         private final String mTelecomCallId;
@@ -362,6 +407,9 @@
             if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
                 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
             }
+            if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
+                builder.append(" CAPABILITY_CAN_PULL_CALL");
+            }
             builder.append("]");
             return builder.toString();
         }
@@ -411,6 +459,9 @@
             if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
                 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
             }
+            if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
+                builder.append(" PROPERTY_IS_EXTERNAL_CALL");
+            }
             builder.append("]");
             return builder.toString();
         }
@@ -723,6 +774,17 @@
          *          conferenced.
          */
         public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
+
+        /**
+         * Invoked when a call receives an event from its associated {@link Connection}.
+         * <p>
+         * See {@link Connection#sendConnectionEvent(String, Bundle)}.
+         *
+         * @param call The {@code Call} receiving the event.
+         * @param event The event.
+         * @param extras Extras associated with the connection event.
+         */
+        public void onConnectionEvent(Call call, String event, Bundle extras) {}
     }
 
     /**
@@ -889,6 +951,43 @@
     }
 
     /**
+     * Initiates a request to the {@link ConnectionService} to pull an external call to the local
+     * device.
+     * <p>
+     * Calls to this method are ignored if the call does not have the
+     * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
+     * <p>
+     * An {@link InCallService} will only see calls which support this method if it has the
+     * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
+     * in its manifest.
+     */
+    public void pullExternalCall() {
+        // If this isn't an external call, ignore the request.
+        if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
+            return;
+        }
+
+        mInCallAdapter.pullExternalCall(mTelecomCallId);
+    }
+
+    /**
+     * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
+     * the {@link ConnectionService}.
+     * <p>
+     * Events are exposed to {@link ConnectionService} implementations via
+     * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
+     * <p>
+     * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
+     * Events should be fully qualified (e.g., com.example.event.MY_EVENT) to avoid conflicts.
+     *
+     * @param event The connection event.
+     * @param extras Bundle containing extra information associated with the event.
+     */
+    public void sendCallEvent(String event, Bundle extras) {
+        mInCallAdapter.sendCallEvent(mTelecomCallId, event, extras);
+    }
+
+    /**
      * Obtains the parent of this {@code Call} in a conference, if any.
      *
      * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
@@ -1211,6 +1310,11 @@
         }
     }
 
+    /** {@hide} */
+    final void internalOnConnectionEvent(String event, Bundle extras) {
+        fireOnConnectionEvent(event, extras);
+    }
+
     private void fireStateChanged(final int newState) {
         for (CallbackRecord<Callback> record : mCallbackRecords) {
             final Call call = this;
@@ -1358,6 +1462,27 @@
     }
 
     /**
+     * Notifies listeners of an incoming connection event.
+     * <p>
+     * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
+     *
+     * @param event
+     * @param extras
+     */
+    private void fireOnConnectionEvent(final String event, final Bundle extras) {
+        for (CallbackRecord<Callback> record : mCallbackRecords) {
+            final Call call = this;
+            final Callback callback = record.getCallback();
+            record.getHandler().post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onConnectionEvent(call, event, extras);
+                }
+            });
+        }
+    }
+
+    /**
      * Determines if two bundles are equal.
      *
      * @param bundle The original bundle.
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 4547c6a..51a6588 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -93,6 +93,15 @@
     public static final int STATE_DISCONNECTED = 6;
 
     /**
+     * The state of an external connection which is in the process of being pulled from a remote
+     * device to the local device.
+     * <p>
+     * A connection can only be in this state if the {@link #CAPABILITY_IS_EXTERNAL_CALL} and
+     * {@link #CAPABILITY_CAN_PULL_CALL} capability bits are set on the connection.
+     */
+    public static final int STATE_PULLING_CALL = 7;
+
+    /**
      * Connection can currently be put on hold or unheld. This is distinct from
      * {@link #CAPABILITY_SUPPORT_HOLD} in that although a connection may support 'hold' most times,
      * it does not at the moment support the function. This can be true while the call is in the
@@ -251,7 +260,6 @@
     /**
      * Indicates that the connection itself wants to handle any sort of reply response, rather than
      * relying on SMS.
-     * @hide
      */
     public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00400000;
 
@@ -270,8 +278,33 @@
      */
     public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00800000;
 
+    /**
+     * When set, indicates that the {@code Connection} does not actually exist locally for the
+     * {@link ConnectionService}.
+     * <p>
+     * Consider, for example, a scenario where a user has two devices with the same phone number.
+     * When a user places a call on one devices, the telephony stack can represent that call on the
+     * other device by adding is to the {@link ConnectionService} with the
+     * {@code CAPABILITY_IS_EXTERNAL_CALL} capability set.
+     * <p>
+     * An {@link ConnectionService} should not assume that all {@link InCallService}s will handle
+     * external connections.  Only those {@link InCallService}s which have the
+     * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
+     * manifest will see external connections.
+     */
+    public static final int CAPABILITY_IS_EXTERNAL_CALL = 0x01000000;
+
+    /**
+     * When set for an external connection, indicates that this {@code Connection} can be pulled
+     * from a remote device to the current device.
+     * <p>
+     * Should only be set on a {@code Connection} where {@link #CAPABILITY_IS_EXTERNAL_CALL}
+     * is set.
+     */
+    public static final int CAPABILITY_CAN_PULL_CALL = 0x02000000;
+
     //**********************************************************************************************
-    // Next CAPABILITY value: 0x01000000
+    // Next CAPABILITY value: 0x04000000
     //**********************************************************************************************
 
     /**
@@ -315,6 +348,18 @@
     public static final String EVENT_ON_HOLD_TONE_END =
             "android.telecom.event.ON_HOLD_TONE_END";
 
+    /**
+     * Connection event used to inform {@link InCallService}s when pulling of an external call has
+     * failed.  The user interface should inform the user of the error.
+     * <p>
+     * Expected to be used by the {@link ConnectionService} when the {@link Call#pullExternalCall()}
+     * API is called on a {@link Call} with the properties
+     * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} and
+     * {@link Call.Details#CAPABILITY_CAN_PULL_CALL}, but the {@link ConnectionService} could not
+     * pull the external call due to an error condition.
+     */
+    public static final String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
+
     // Flag controlling whether PII is emitted into the logs
     private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);
 
@@ -434,6 +479,12 @@
         if (can(capabilities, CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION)) {
             builder.append(" CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION");
         }
+        if (can(capabilities, CAPABILITY_IS_EXTERNAL_CALL)) {
+            builder.append(" CAPABILITY_IS_EXTERNAL_CALL");
+        }
+        if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
+            builder.append(" CAPABILITY_CAN_PULL_CALL");
+        }
 
         builder.append("]");
         return builder.toString();
@@ -465,8 +516,7 @@
         public void onConferenceStarted() {}
         public void onConferenceMergeFailed(Connection c) {}
         public void onExtrasChanged(Connection c, Bundle extras) {}
-        /** @hide */
-        public void onConnectionEvent(Connection c, String event) {}
+        public void onConnectionEvent(Connection c, String event, Bundle extras) {}
     }
 
     /**
@@ -1836,9 +1886,8 @@
     public void onReject() {}
 
     /**
-     * Notifies ths Connection of a request reject with a message.
-     *
-     * @hide
+     * Notifies this Connection, which is in {@link #STATE_RINGING}, of
+     * a request to reject with a message.
      */
     public void onReject(String replyMessage) {}
 
@@ -1854,6 +1903,31 @@
      */
     public void onPostDialContinue(boolean proceed) {}
 
+    /**
+     * Notifies this Connection of a request to pull an external call to the local device.
+     * <p>
+     * The {@link InCallService} issues a request to pull an external call to the local device via
+     * {@link Call#pullExternalCall()}.
+     * <p>
+     * For a Connection to be pulled, both the {@link Connection#CAPABILITY_CAN_PULL_CALL} and
+     * {@link Connection#CAPABILITY_IS_EXTERNAL_CALL} capability bits must be set.
+     * <p>
+     * For more information on external calls, see {@link Connection#CAPABILITY_IS_EXTERNAL_CALL}.
+     */
+    public void onPullExternalCall() {}
+
+    /**
+     * Notifies this Connection of a {@link Call} event initiated from an {@link InCallService}.
+     * <p>
+     * The {@link InCallService} issues a Call event via {@link Call#sendCallEvent(String, Bundle)}.
+     * <p>
+     * See also {@link Call#sendCallEvent(String, Bundle)}.
+     *
+     * @param event The call event.
+     * @param extras Extras associated with the call event.
+     */
+    public void onCallEvent(String event, Bundle extras) {}
+
     static String toLogSafePhoneNumber(String number) {
         // For unknown number, log empty string.
         if (number == null) {
@@ -2008,14 +2082,20 @@
     }
 
     /**
-     * Sends a connection event to Telecom.
+     * Sends an event associated with this {@code Connection}, with associated event extras.
+     *
+     * Events are exposed to {@link InCallService} implementations via the
+     * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)} API.
+     *
+     * No assumptions should be made as to how an In-Call UI or service will handle these events.
+     * Events should be fully qualified (e.g., com.example.event.MY_EVENT) to avoid conflicts.
      *
      * @param event The connection event.
-     * @hide
+     * @param extras Bundle containing extra information associated with the event.
      */
-    protected void sendConnectionEvent(String event) {
+    public void sendConnectionEvent(String event, Bundle extras) {
         for (Listener l : mListeners) {
-            l.onConnectionEvent(this, event);
+            l.onConnectionEvent(this, event, null);
         }
     }
 }
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 5b62e03..d18b317 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -103,6 +103,8 @@
     private static final int MSG_SWAP_CONFERENCE = 19;
     private static final int MSG_REJECT_WITH_MESSAGE = 20;
     private static final int MSG_SILENCE = 21;
+    private static final int MSG_PULL_EXTERNAL_CALL = 22;
+    private static final int MSG_SEND_CALL_EVENT = 23;
 
     private static Connection sNullConnection;
 
@@ -245,6 +247,20 @@
             args.argi1 = proceed ? 1 : 0;
             mHandler.obtainMessage(MSG_ON_POST_DIAL_CONTINUE, args).sendToTarget();
         }
+
+        @Override
+        public void pullExternalCall(String callId) {
+            mHandler.obtainMessage(MSG_PULL_EXTERNAL_CALL, callId).sendToTarget();
+        }
+
+        @Override
+        public void sendCallEvent(String callId, String event, Bundle extras) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = callId;
+            args.arg2 = event;
+            args.arg3 = extras;
+            mHandler.obtainMessage(MSG_SEND_CALL_EVENT, args).sendToTarget();
+        }
     };
 
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -382,6 +398,22 @@
                     }
                     break;
                 }
+                case MSG_PULL_EXTERNAL_CALL: {
+                    pullExternalCall((String) msg.obj);
+                    break;
+                }
+                case MSG_SEND_CALL_EVENT: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        String callId = (String) args.arg1;
+                        String event = (String) args.arg2;
+                        Bundle extras = (Bundle) args.arg3;
+                        sendCallEvent(callId, event, extras);
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
                 default:
                     break;
             }
@@ -615,10 +647,10 @@
         }
 
         @Override
-        public void onConnectionEvent(Connection connection, String event) {
+        public void onConnectionEvent(Connection connection, String event, Bundle extras) {
             String id = mIdByConnection.get(connection);
             if (id != null) {
-                mAdapter.onConnectionEvent(id, event);
+                mAdapter.onConnectionEvent(id, event, extras);
             }
         }
     };
@@ -864,6 +896,39 @@
         }
     }
 
+    /**
+     * Notifies a {@link Connection} of a request to pull an external call.
+     *
+     * See {@link Call#pullExternalCall()}.
+     *
+     * @param callId The ID of the call to pull.
+     */
+    private void pullExternalCall(String callId) {
+        Log.d(this, "pullExternalCall(%s)", callId);
+        Connection connection = findConnectionForAction(callId, "pullExternalCall");
+        if (connection != null) {
+            connection.onPullExternalCall();
+        }
+    }
+
+    /**
+     * Notifies a {@link Connection} of a call event.
+     *
+     * See {@link Call#sendCallEvent(String, Bundle)}.
+     *
+     * @param callId The ID of the call receiving the event.
+     * @param event The event.
+     * @param extras Extras associated with the event.
+     */
+    private void sendCallEvent(String callId, String event, Bundle extras) {
+        Log.d(this, "sendCallEvent(%s, %s)", callId, event);
+        Connection connection = findConnectionForAction(callId, "sendCallEvent");
+        if (connection != null) {
+            connection.onCallEvent(event, extras);
+        }
+
+    }
+
     private void onPostDialContinue(String callId, boolean proceed) {
         Log.d(this, "onPostDialContinue(%s)", callId);
         findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index 30fc5ad..e91128f 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -418,12 +418,13 @@
      *
      * @param callId The unique ID of the call.
      * @param event The event.
+     * @param extras Extras associated with the event.
      */
-    void onConnectionEvent(String callId, String event) {
+    void onConnectionEvent(String callId, String event, Bundle extras) {
         Log.v(this, "onConnectionEvent: %s", event);
         for (IConnectionServiceAdapter adapter : mAdapters) {
             try {
-                adapter.onConnectionEvent(callId, event);
+                adapter.onConnectionEvent(callId, event, extras);
             } catch (RemoteException ignored) {
             }
         }
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index 6a8c1cb..4b15e54 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -245,7 +245,8 @@
                 case MSG_ON_CONNECTION_EVENT: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
-                        mDelegate.onConnectionEvent((String) args.arg1, (String) args.arg2);
+                        mDelegate.onConnectionEvent((String) args.arg1, (String) args.arg2,
+                                (Bundle) args.arg3);
                     } finally {
                         args.recycle();
                     }
@@ -432,10 +433,11 @@
         }
 
         @Override
-        public final void onConnectionEvent(String connectionId, String event) {
+        public final void onConnectionEvent(String connectionId, String event, Bundle extras) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = connectionId;
             args.arg2 = event;
+            args.arg3 = extras;
             mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
         }
     };
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index 2eef7ee..cf73d4f 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -64,6 +64,17 @@
      */
     public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10;
 
+    /**
+     * Disconnected because the user did not locally answer the incoming call, but it was answered
+     * on another device where the call was ringing.
+     */
+    public static final int ANSWERED_ELSEWHERE = 11;
+
+    /**
+     * Disconnected because the call was pulled from the current device to another device.
+     */
+    public static final int CALL_PULLED = 12;
+
     private int mDisconnectCode;
     private CharSequence mDisconnectLabel;
     private CharSequence mDisconnectDescription;
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 0cf7212b..52ef4a7 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.os.Bundle;
 import android.os.RemoteException;
 
 import com.android.internal.telecom.IInCallAdapter;
@@ -251,6 +252,32 @@
     }
 
     /**
+     * Instructs Telecom to pull an external call to the local device.
+     *
+     * @param callId The callId to pull.
+     */
+    public void pullExternalCall(String callId) {
+        try {
+            mAdapter.pullExternalCall(callId);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
+     * Intructs Telecom to send a call event.
+     *
+     * @param callId The callId to send the event for.
+     * @param event The event.
+     * @param extras Extras associated with the event.
+     */
+    public void sendCallEvent(String callId, String event, Bundle extras) {
+        try {
+            mAdapter.sendCallEvent(callId, event, extras);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
      * Instructs Telecom to turn the proximity sensor on.
      */
     public void turnProximitySensorOn() {
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 671399b..df6715d 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.hardware.camera2.CameraManager;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -74,6 +75,7 @@
     private static final int MSG_BRING_TO_FOREGROUND = 6;
     private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7;
     private static final int MSG_SILENCE_RINGER = 8;
+    private static final int MSG_ON_CONNECTION_EVENT = 9;
 
     /** Default Handler used to consolidate binder method calls onto a single thread. */
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -118,6 +120,18 @@
                 case MSG_SILENCE_RINGER:
                     mPhone.internalSilenceRinger();
                     break;
+                case MSG_ON_CONNECTION_EVENT: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        String callId = (String) args.arg1;
+                        String event = (String) args.arg2;
+                        Bundle extras = (Bundle) args.arg3;
+                        mPhone.internalOnConnectionEvent(callId, event, extras);
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
                 default:
                     break;
             }
@@ -174,6 +188,15 @@
         public void silenceRinger() {
             mHandler.obtainMessage(MSG_SILENCE_RINGER).sendToTarget();
         }
+
+        @Override
+        public void onConnectionEvent(String callId, String event, Bundle extras) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = callId;
+            args.arg2 = event;
+            args.arg3 = extras;
+            mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget();
+        }
     }
 
     private Phone.Listener mPhoneListener = new Phone.Listener() {
@@ -426,6 +449,19 @@
     }
 
     /**
+     * Called when a {@link Call} has received a connection event issued by the
+     * {@link ConnectionService}.
+     * <p>
+     * See {@link Connection#sendConnectionEvent(String, Bundle)}.
+     *
+     * @param call The call the event is associated with.
+     * @param event The event.
+     * @param extras Any associated extras.
+     */
+    public void onConnectionEvent(Call call, String event, Bundle extras) {
+    }
+
+    /**
      * Used to issue commands to the {@link Connection.VideoProvider} associated with a
      * {@link Call}.
      */
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index d45938c..a4ef560 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -17,6 +17,7 @@
 package android.telecom;
 
 import android.annotation.SystemApi;
+import android.os.Bundle;
 import android.util.ArrayMap;
 
 import java.util.Collections;
@@ -190,6 +191,13 @@
         fireSilenceRinger();
     }
 
+    final void internalOnConnectionEvent(String telecomId, String event, Bundle extras) {
+        Call call = mCallByTelecomCallId.get(telecomId);
+        if (call != null) {
+            call.internalOnConnectionEvent(event, extras);
+        }
+    }
+
     /**
      * Called to destroy the phone and cleanup any lingering calls.
      */
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 0185808..5b602eb 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -212,12 +212,14 @@
 
         /**
          * Handles a connection event propagated to this {@link RemoteConnection}.
+         * <p>
+         * Connection events originate from {@link Connection#sendConnectionEvent(String, Bundle)}.
          *
          * @param connection The {@code RemoteConnection} invoking this method.
          * @param event The connection event.
-         * @hide
+         * @param extras Extras associated with the event.
          */
-        public void onConnectionEvent(RemoteConnection connection, String event) {}
+        public void onConnectionEvent(RemoteConnection connection, String event, Bundle extras) {}
     }
 
     /**
@@ -962,6 +964,20 @@
     }
 
     /**
+     * Instructs this {@link RemoteConnection} to pull itself to the local device.
+     * <p>
+     * See {@link Call#pullExternalCall()} for more information.
+     */
+    public void pullExternalCall() {
+        try {
+            if (mConnected) {
+                mConnectionService.pullExternalCall(mConnectionId);
+            }
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
      * Set the audio state of this {@code RemoteConnection}.
      *
      * @param state The audio state of this {@code RemoteConnection}.
@@ -1301,14 +1317,14 @@
     }
 
     /** @hide */
-    void onConnectionEvent(final String event) {
+    void onConnectionEvent(final String event, final Bundle extras) {
         for (CallbackRecord record : mCallbackRecords) {
             final RemoteConnection connection = this;
             final Callback callback = record.getCallback();
             record.getHandler().post(new Runnable() {
                 @Override
                 public void run() {
-                    callback.onConnectionEvent(connection, event);
+                    callback.onConnectionEvent(connection, event, extras);
                 }
             });
         }
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index b85382f..fa7183a 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -332,9 +332,10 @@
         }
 
         @Override
-        public void onConnectionEvent(String callId, String event) {
+        public void onConnectionEvent(String callId, String event, Bundle extras) {
             if (mConnectionById.containsKey(callId)) {
-                findConnectionForAction(callId, "onConnectionEvent").onConnectionEvent(event);
+                findConnectionForAction(callId, "onConnectionEvent").onConnectionEvent(event,
+                        extras);
             }
         }
     };
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 605e0d3..4fa8fe9 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -317,6 +317,18 @@
             "android.telecom.IN_CALL_SERVICE_RINGING";
 
     /**
+     * A boolean meta-data value indicating whether an {@link InCallService} wants to be informed of
+     * calls which have the {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property.  An external
+     * call is one which a {@link ConnectionService} knows about, but is not connected to directly.
+     * Dialer implementations (see {@link #getDefaultDialerPackage()}) which would like to be
+     * informed of external calls should set this meta-data to {@code true} in the manifest
+     * registration of their {@link InCallService}.  By default, the {@link InCallService} will NOT
+     * be informed of external calls.
+     */
+    public static final String METADATA_INCLUDE_EXTERNAL_CALLS =
+            "android.telecom.INCLUDE_EXTERNAL_CALLS";
+
+    /**
      * The dual tone multi-frequency signaling character sent to indicate the dialing system should
      * pause for a predefined period.
      */
@@ -1442,7 +1454,7 @@
     /**
      * Creates the {@link Intent} which can be used with {@link Context#startActivity(Intent)} to
      * launch the activity to manage blocked numbers.
-     * <p> This method displays the UI to manage blocked numbers only if
+     * <p> The activity will display the UI to manage blocked numbers only if
      * {@link android.provider.BlockedNumberContract#canCurrentUserBlockNumbers(Context)} returns
      * {@code true} for the current user.
      */
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 8a54add..3ee0e9f 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -75,4 +75,8 @@
     void swapConference(String conferenceCallId);
 
     void onPostDialContinue(String callId, boolean proceed);
+
+    void pullExternalCall(String callId);
+
+    void sendCallEvent(String callId, String event, in Bundle extras);
 }
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index 569c244..dff1b11 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -87,5 +87,5 @@
 
     void setExtras(String callId, in Bundle extras);
 
-    void onConnectionEvent(String callId, String event);
+    void onConnectionEvent(String callId, String event, in Bundle extras);
 }
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index 863fff2..0678fe2 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -16,6 +16,7 @@
 
 package com.android.internal.telecom;
 
+import android.os.Bundle;
 import android.telecom.PhoneAccountHandle;
 
 /**
@@ -60,4 +61,8 @@
     void turnOnProximitySensor();
 
     void turnOffProximitySensor(boolean screenOnImmediately);
+
+    void pullExternalCall(String callId);
+
+    void sendCallEvent(String callId, String event, in Bundle extras);
 }
diff --git a/telecomm/java/com/android/internal/telecom/IInCallService.aidl b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
index 0088e0c..3e43fe2 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallService.aidl
@@ -17,6 +17,7 @@
 package com.android.internal.telecom;
 
 import android.app.PendingIntent;
+import android.os.Bundle;
 import android.telecom.CallAudioState;
 import android.telecom.ParcelableCall;
 
@@ -47,4 +48,6 @@
     void onCanAddCallChanged(boolean canAddCall);
 
     void silenceRinger();
+
+    void onConnectionEvent(String callId, String event, in Bundle extras);
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index ea437d0..86518b5 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -444,6 +444,11 @@
     public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
 
     /**
+     * Flag specifying whether ICCID is showed in SIM Status screen, default to false.
+     */
+    public static final String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
+
+    /**
      * Flag specifying whether an additional (client initiated) intent needs to be sent on System
      * update
      */
@@ -680,6 +685,7 @@
         sDefaults.putBoolean(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN,false);
         sDefaults.putBoolean(KEY_VVM_PREFETCH_BOOLEAN,true);
         sDefaults.putString(KEY_CARRIER_VVM_PACKAGE_NAME_STRING, "");
+        sDefaults.putBoolean(KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL, false);
         sDefaults.putBoolean(KEY_CI_ACTION_ON_SYS_UPDATE_BOOL, false);
         sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING, "");
         sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING, "");
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java b/telephony/java/com/android/ims/ImsExternalCallState.aidl
similarity index 66%
copy from packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
copy to telephony/java/com/android/ims/ImsExternalCallState.aidl
index 55f55b0..c208702 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
+++ b/telephony/java/com/android/ims/ImsExternalCallState.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (c) 2016 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,12 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.mtp.exceptions;
+package com.android.ims;
 
-import java.io.IOException;
-
-/**
- * Exception thrown when the device is busy and the requested operation cannon be completed.
- */
-public class BusyDeviceException extends IOException {
-}
+parcelable ImsExternalCallState;
diff --git a/telephony/java/com/android/ims/ImsExternalCallState.java b/telephony/java/com/android/ims/ImsExternalCallState.java
new file mode 100644
index 0000000..edb6bfc
--- /dev/null
+++ b/telephony/java/com/android/ims/ImsExternalCallState.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2016 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.ims;
+
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.Rlog;
+
+/*
+ * This file contains all the api's through which
+ * information received in Dialog Event Package can be
+ * queried
+ */
+
+/**
+ * Parcelable object to handle VICE Dialog Information
+ * @hide
+ */
+public class ImsExternalCallState implements Parcelable {
+
+    private static final String TAG = "ImsExternalCallState";
+
+    // Dialog States
+    public static final int CALL_STATE_CONFIRMED = 1;
+    public static final int CALL_STATE_TERMINATED = 2;
+    // Dialog Id
+    public int mCallId;
+    // Number
+    public Uri mAddress;
+    public boolean mIsPullable;
+    // CALL_STATE_CONFIRMED / CALL_STATE_TERMINATED
+    public int mCallState;
+    // ImsCallProfile#CALL_TYPE_*
+    public int mCallType;
+    public boolean mIsHeld;
+
+    public ImsExternalCallState() {
+    }
+
+    public ImsExternalCallState(Parcel in) {
+        mCallId = in.readInt();
+        ClassLoader classLoader = ImsExternalCallState.class.getClassLoader();
+        mAddress = in.readParcelable(classLoader);
+        mIsPullable = (in.readInt() != 0);
+        mCallState = in.readInt();
+        mCallType = in.readInt();
+        mIsHeld = (in.readInt() != 0);
+        Rlog.d(TAG, "ImsExternalCallState const = " +
+                "callid = " + getCallId() +
+                ", address = " + getAddress() +
+                ", mCallState = " + getCallState() +
+                ", calltype = " + getCallType() +
+                ", isheld = " + isCallHeld());
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mCallId);
+        out.writeParcelable(mAddress, 0);
+        out.writeInt(mIsPullable ? 1 : 0);
+        out.writeInt(mCallState);
+        out.writeInt(mCallType);
+        out.writeInt(mIsHeld ? 1 : 0);
+    }
+
+    public static final Parcelable.Creator<ImsExternalCallState> CREATOR =
+            new Parcelable.Creator<ImsExternalCallState>() {
+        @Override
+        public ImsExternalCallState createFromParcel(Parcel in) {
+            return new ImsExternalCallState(in);
+        }
+
+        @Override
+        public ImsExternalCallState[] newArray(int size) {
+            return new ImsExternalCallState[size];
+        }
+    };
+
+    public int getCallId() {
+        return mCallId;
+    }
+
+    public Uri getAddress() {
+        return mAddress;
+    }
+
+    public boolean isCallPullable() {
+        return mIsPullable;
+    }
+
+    public int getCallState() {
+        return mCallState;
+    }
+
+    public int getCallType() {
+        return mCallType;
+    }
+
+    public boolean isCallHeld() {
+        return mIsHeld;
+    }
+
+    @Override
+    public String toString() {
+        return "ImsExternalCallState { mCallId = " + mCallId +
+                ", mAddress = " + mAddress +
+                ", mIsPullable = " + mIsPullable +
+                ", mCallState = " + mCallState +
+                ", mCallType = " + mCallType +
+                ", mIsHeld = " + mIsHeld + "}";
+    }
+}
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index 558c1dc..f06d154 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -241,12 +241,12 @@
     public static final int CODE_ANSWERED_ELSEWHERE = 1014;
 
     /**
-     * Call pull request failure from the network.
+     * For MultiEndpoint - Call Pull request has failed
      */
     public static final int CODE_CALL_PULL_OUT_OF_SYNC = 1015;
 
     /**
-     * Call ended due to being pulled onto another device.
+     * For MultiEndpoint - Call has been pulled from primary to secondary
      */
     public static final int CODE_CALL_END_CAUSE_CALL_PULL = 1016;
 
diff --git a/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl b/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl
new file mode 100644
index 0000000..70a474e
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016 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.ims.internal;
+
+import com.android.ims.ImsExternalCallState;
+
+/**
+ * A listener type for receiving notifications about DEP through IMS
+ *
+ * {@hide}
+ */
+interface IImsExternalCallStateListener {
+
+    /**
+     * Notifies client when Dialog Event Package update is received
+     *
+     * @param List<ImsExternalCallState> - External Call Dialog
+     *
+     * @return void.
+     */
+    void notifyRefreshExternalCallState(in List<ImsExternalCallState> externalCallDialogs);
+
+}
+
diff --git a/telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl b/telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl
new file mode 100644
index 0000000..1bfb9b2
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016 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.ims.internal;
+
+import com.android.ims.internal.IImsExternalCallStateListener;
+
+/**
+ * Provides the ImsMultiEndpoint interface
+ *
+ * {@hide}
+ */
+interface IImsMultiEndpoint {
+    /**
+     * Sets the listener.
+     */
+    void setListener(in IImsExternalCallStateListener listener);
+
+
+    /**
+     * Query api to get the latest Dialog Event Package information
+     * Should be invoked only after setListener is done
+     */
+    void requestDialogEventPackageState();
+}
diff --git a/telephony/java/com/android/ims/internal/IImsService.aidl b/telephony/java/com/android/ims/internal/IImsService.aidl
index 30c48d7..a9614a6 100644
--- a/telephony/java/com/android/ims/internal/IImsService.aidl
+++ b/telephony/java/com/android/ims/internal/IImsService.aidl
@@ -19,12 +19,13 @@
 import android.app.PendingIntent;
 
 import com.android.ims.ImsCallProfile;
-import com.android.ims.internal.IImsRegistrationListener;
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsCallSessionListener;
-import com.android.ims.internal.IImsEcbm;
-import com.android.ims.internal.IImsUt;
 import com.android.ims.internal.IImsConfig;
+import com.android.ims.internal.IImsEcbm;
+import com.android.ims.internal.IImsMultiEndpoint;
+import com.android.ims.internal.IImsRegistrationListener;
+import com.android.ims.internal.IImsUt;
 
 import android.os.Message;
 
@@ -75,4 +76,9 @@
      * Used to set current TTY Mode.
      */
     void setUiTTYMode(int serviceId, int uiTtyMode, in Message onComplete);
+
+    /**
+     * MultiEndpoint interface for DEP.
+     */
+    IImsMultiEndpoint getMultiEndpointInterface(int serviceId);
 }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index bba357e..4f0e036 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -92,6 +92,17 @@
     int NO_SMS_TO_ACK = 48;                   /* ACK received when there is no SMS to ack */
     int NETWORK_ERR = 49;                     /* Received error from network */
     int REQUEST_RATE_LIMITED = 50;            /* Operation denied due to overly-frequent requests */
+    int SIM_BUSY = 51;                        /* SIM is busy */
+    int SIM_FULL = 52;                        /* The target EF is full */
+    int NETWORK_REJECT = 53;                  /* Request is rejected by network */
+    int OPERATION_NOT_ALLOWED = 54;           /* Not allowed the request now */
+    int EMPTY_RECORD = 55;                    /* The request record is empty */
+    int INVALID_SMS_FORMAT = 56;              /* Invalid sms format */
+    int ENCODING_ERR = 57;                    /* Message not encoded properly */
+    int INVALID_SMSC_ADDRESS = 58;            /* SMSC address specified is invalid */
+    int NO_SUCH_ENTRY = 59;                   /* No such entry present to perform the request */
+    int NETWORK_NOT_READY = 60;               /* Network is not ready to perform the request */
+    int NOT_PROVISIONED = 61;                 /* Device doesnot have this value provisioned */
     // Below is list of OEM specific error codes which can by used by OEMs in case they don't want to
     // reveal particular replacement for Generic failure
     int OEM_ERROR_1 = 501;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 645c3a1..ea3b5c9 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -217,4 +217,12 @@
      *     or Earpiece, based on the default audio routing strategy.
      */
     static final String PROPERTY_VIDEOCALL_AUDIO_OUTPUT = "persist.radio.call.audio.output";
+
+    /**
+     * For MultiEndpoint Feature
+     * If true: Dial intent is for call pull functionality
+     * if false: normal dial
+     */
+    static final String EXTRA_IS_CALL_PULL =
+            "android.telephony.extra.IS_CALL_PULL";
 }
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index e851c8d..91e891f 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -758,6 +758,12 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public void flushPackageRestrictionsAsUser(int userId) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public void addPreferredActivity(IntentFilter filter,
             int match, ComponentName[] set, ComponentName activity) {
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rs b/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rs
index caa947d..0a1742e 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rs
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/errorCalculator.rs
@@ -14,10 +14,14 @@
 
     for (int x = 0; x < HEIGHT; x += REGION_SIZE) {
         bool interestingRegion = false;
-        int regionColor = (int) rsGetElementAt_uchar4(ideal, x, y);
+        uchar4 regionColor = rsGetElementAt_uchar4(ideal, x, y);
         for (int i = 0; i < REGION_SIZE && !interestingRegion; i++) {
             for (int j = 0; j < REGION_SIZE && !interestingRegion; j++) {
-                interestingRegion |= ((int) rsGetElementAt_uchar4(ideal, x + j, y + i)) != regionColor;
+                uchar4 testVal = rsGetElementAt_uchar4(ideal, x + j, y + i);
+                interestingRegion |= (testVal.r != regionColor.r);
+                interestingRegion |= (testVal.g != regionColor.g);
+                interestingRegion |= (testVal.b != regionColor.b);
+                interestingRegion |= (testVal.a != regionColor.a);
             }
         }
         if (interestingRegion) {
diff --git a/tests/NetworkSecurityConfigTest/res/xml/bad_extra_debug_resource.xml b/tests/NetworkSecurityConfigTest/res/xml/bad_extra_debug_resource.xml
new file mode 100644
index 0000000..8093b9d
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/xml/bad_extra_debug_resource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+  <base-config>
+    <trust-anchors>
+    </trust-anchors>
+  </base-config>
+</network-security-config>
diff --git a/tests/NetworkSecurityConfigTest/res/xml/bad_extra_debug_resource_debug.xml b/tests/NetworkSecurityConfigTest/res/xml/bad_extra_debug_resource_debug.xml
new file mode 100644
index 0000000..fc24df5
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/xml/bad_extra_debug_resource_debug.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- debug-overrides not inside network-security-config should cause a parsing error -->
+<debug-overrides>
+  <trust-anchors>
+    <certificates src="system" />
+  </trust-anchors>
+</debug-overrides>
diff --git a/tests/NetworkSecurityConfigTest/res/xml/extra_debug_resource.xml b/tests/NetworkSecurityConfigTest/res/xml/extra_debug_resource.xml
new file mode 100644
index 0000000..8093b9d
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/xml/extra_debug_resource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+  <base-config>
+    <trust-anchors>
+    </trust-anchors>
+  </base-config>
+</network-security-config>
diff --git a/tests/NetworkSecurityConfigTest/res/xml/extra_debug_resource_debug.xml b/tests/NetworkSecurityConfigTest/res/xml/extra_debug_resource_debug.xml
new file mode 100644
index 0000000..6a2ad37
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/xml/extra_debug_resource_debug.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+  <debug-overrides>
+    <trust-anchors>
+      <certificates src="system" />
+    </trust-anchors>
+  </debug-overrides>
+</network-security-config>
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
index 35e3ef4..10bcc18 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
@@ -431,4 +431,37 @@
         TestUtils.assertConnectionSucceeds(context, "android.com", 443);
         TestUtils.assertUrlConnectionSucceeds(context, "android.com", 443);
     }
+
+    public void testExtraDebugResource() throws Exception {
+        XmlConfigSource source =
+                new XmlConfigSource(getContext(), R.xml.extra_debug_resource, true);
+        ApplicationConfig appConfig = new ApplicationConfig(source);
+        assertFalse(appConfig.hasPerDomainConfigs());
+        NetworkSecurityConfig config = appConfig.getConfigForHostname("");
+        MoreAsserts.assertNotEmpty(config.getTrustAnchors());
+
+        // Check that the _debug file is ignored if debug is false.
+        source = new XmlConfigSource(getContext(), R.xml.extra_debug_resource, false);
+        appConfig = new ApplicationConfig(source);
+        assertFalse(appConfig.hasPerDomainConfigs());
+        config = appConfig.getConfigForHostname("");
+        MoreAsserts.assertEmpty(config.getTrustAnchors());
+    }
+
+    public void testExtraDebugResourceIgnored() throws Exception {
+        // Verify that parsing the extra debug config resource fails only when debugging is true.
+        XmlConfigSource source =
+                new XmlConfigSource(getContext(), R.xml.bad_extra_debug_resource, false);
+        ApplicationConfig appConfig = new ApplicationConfig(source);
+        // Force parsing the config file.
+        appConfig.getConfigForHostname("");
+
+        source = new XmlConfigSource(getContext(), R.xml.bad_extra_debug_resource, true);
+        appConfig = new ApplicationConfig(source);
+        try {
+            appConfig.getConfigForHostname("");
+            fail("Bad extra debug resource did not fail to parse");
+        } catch (RuntimeException expected) {
+        }
+    }
 }
diff --git a/tests/SoundTriggerTests/Android.mk b/tests/SoundTriggerTests/Android.mk
index ac562b9..e67134d 100644
--- a/tests/SoundTriggerTests/Android.mk
+++ b/tests/SoundTriggerTests/Android.mk
@@ -27,6 +27,7 @@
   LOCAL_SRC_FILES := src/android/hardware/soundtrigger/SoundTriggerTest.java
 endif
 
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_PACKAGE_NAME := SoundTriggerTests
diff --git a/tests/SoundTriggerTests/AndroidManifest.xml b/tests/SoundTriggerTests/AndroidManifest.xml
index e8b9dd3..f7454c7 100644
--- a/tests/SoundTriggerTests/AndroidManifest.xml
+++ b/tests/SoundTriggerTests/AndroidManifest.xml
@@ -17,7 +17,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="android.hardware.soundtrigger">
     <uses-permission android:name="android.permission.MANAGE_SOUND_TRIGGER" />
-
+    <uses-permission android:name="android.permission.INTERNET" />
+    
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
diff --git a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
index 7acb472..ad02d2b 100644
--- a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
+++ b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
@@ -16,70 +16,180 @@
 
 package android.hardware.soundtrigger;
 
-import java.util.Random;
-import java.util.UUID;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
 
 import android.content.Context;
+import android.hardware.soundtrigger.SoundTrigger.GenericRecognitionEvent;
 import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent;
+import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
 import android.media.soundtrigger.SoundTriggerManager;
 import android.os.ParcelUuid;
 import android.os.ServiceManager;
 import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.internal.app.ISoundTriggerService;
 
-import java.util.Arrays;
+import java.io.DataOutputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.util.ArrayList;
 import java.util.Random;
 import java.util.UUID;
 
+import org.mockito.MockitoAnnotations;
+
 public class GenericSoundModelTest extends AndroidTestCase {
-    private Random mRandom = new Random();
+    static final int MSG_DETECTION_ERROR = -1;
+    static final int MSG_DETECTION_RESUME = 0;
+    static final int MSG_DETECTION_PAUSE = 1;
+    static final int MSG_KEYPHRASE_TRIGGER = 2;
+    static final int MSG_GENERIC_TRIGGER = 4;
+
+    private Random random = new Random();
+    private ArrayList<UUID> loadedModelUuids;
+    private ISoundTriggerService soundTriggerService;
+    private SoundTriggerManager soundTriggerManager;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        MockitoAnnotations.initMocks(this);
+
+        Context context = getContext();
+        soundTriggerService = ISoundTriggerService.Stub.asInterface(
+                ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
+        soundTriggerManager = (SoundTriggerManager) context.getSystemService(
+                Context.SOUND_TRIGGER_SERVICE);
+
+        loadedModelUuids = new ArrayList<UUID>();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        for (UUID modelUuid : loadedModelUuids) {
+            soundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid));
+        }
+        super.tearDown();
+    }
+
+    GenericSoundModel new_sound_model() {
+        // Create sound model
+        byte[] data = new byte[1024];
+        random.nextBytes(data);
+        UUID modelUuid = UUID.randomUUID();
+        UUID mVendorUuid = UUID.randomUUID();
+        return new GenericSoundModel(modelUuid, mVendorUuid, data);
+    }
 
     @SmallTest
     public void testUpdateGenericSoundModel() throws Exception {
-        Context context = getContext();
-        ISoundTriggerService mSoundTriggerService = ISoundTriggerService.Stub.asInterface(
-            ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
-        SoundTriggerManager mSoundTriggerManager = (SoundTriggerManager) context.getSystemService(
-            Context.SOUND_TRIGGER_SERVICE);
+        GenericSoundModel model = new_sound_model();
 
-        byte[] data = new byte[1024];
-        mRandom.nextBytes(data);
-        UUID modelUuid = UUID.randomUUID();
-        UUID mVendorUuid = UUID.randomUUID();
-        GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data);
+        // Update sound model
+        soundTriggerService.updateSoundModel(model);
+        loadedModelUuids.add(model.uuid);
 
-        mSoundTriggerService.updateSoundModel(model);
+        // Confirm it was updated
         GenericSoundModel returnedModel =
-            mSoundTriggerService.getSoundModel(new ParcelUuid(modelUuid));
-
+                soundTriggerService.getSoundModel(new ParcelUuid(model.uuid));
         assertEquals(model, returnedModel);
-
-        // Cleanup sound model
-        mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid));
     }
 
-
     @SmallTest
     public void testDeleteGenericSoundModel() throws Exception {
-        Context context = getContext();
-        ISoundTriggerService mSoundTriggerService = ISoundTriggerService.Stub.asInterface(
-            ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
-        SoundTriggerManager mSoundTriggerManager = (SoundTriggerManager) context.getSystemService(
-            Context.SOUND_TRIGGER_SERVICE);
+        GenericSoundModel model = new_sound_model();
 
-        byte[] data = new byte[1024];
-        mRandom.nextBytes(data);
-        UUID modelUuid = UUID.randomUUID();
-        UUID mVendorUuid = UUID.randomUUID();
-        GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data);
+        // Update sound model
+        soundTriggerService.updateSoundModel(model);
+        loadedModelUuids.add(model.uuid);
 
-        mSoundTriggerService.updateSoundModel(model);
-        mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid));
+        // Delete sound model
+        soundTriggerService.deleteSoundModel(new ParcelUuid(model.uuid));
+        loadedModelUuids.remove(model.uuid);
 
+        // Confirm it was deleted
         GenericSoundModel returnedModel =
-            mSoundTriggerService.getSoundModel(new ParcelUuid(modelUuid));
+                soundTriggerService.getSoundModel(new ParcelUuid(model.uuid));
         assertEquals(null, returnedModel);
     }
+
+    @LargeTest
+    public void testStartStopGenericSoundModel() throws Exception {
+        GenericSoundModel model = new_sound_model();
+
+        boolean captureTriggerAudio = true;
+        boolean allowMultipleTriggers = true;
+        RecognitionConfig config = new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers,
+                null, null);
+        TestRecognitionStatusCallback spyCallback = spy(new TestRecognitionStatusCallback());
+
+        // Update and start sound model recognition
+        soundTriggerService.updateSoundModel(model);
+        loadedModelUuids.add(model.uuid);
+        int r = soundTriggerService.startRecognition(new ParcelUuid(model.uuid), spyCallback,
+                config);
+        assertEquals("Could Not Start Recognition with code: " + r,
+                android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
+
+        // Stop recognition
+        r = soundTriggerService.stopRecognition(new ParcelUuid(model.uuid), spyCallback);
+        assertEquals("Could Not Stop Recognition with code: " + r,
+                android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r);
+    }
+
+    @LargeTest
+    public void testTriggerGenericSoundModel() throws Exception {
+        GenericSoundModel model = new_sound_model();
+
+        boolean captureTriggerAudio = true;
+        boolean allowMultipleTriggers = true;
+        RecognitionConfig config = new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers,
+                null, null);
+        TestRecognitionStatusCallback spyCallback = spy(new TestRecognitionStatusCallback());
+
+        // Update and start sound model
+        soundTriggerService.updateSoundModel(model);
+        loadedModelUuids.add(model.uuid);
+        soundTriggerService.startRecognition(new ParcelUuid(model.uuid), spyCallback, config);
+
+        // Send trigger to stub HAL
+        Socket socket = new Socket(InetAddress.getLocalHost(), 14035);
+        DataOutputStream out = new DataOutputStream(socket.getOutputStream());
+        out.writeBytes("trig " + model.uuid.toString() + "\r\n");
+        out.flush();
+        socket.close();
+
+        // Verify trigger was received
+        verify(spyCallback, timeout(100)).onGenericSoundTriggerDetected(any());
+    }
+
+
+    public class TestRecognitionStatusCallback extends IRecognitionStatusCallback.Stub {
+        @Override
+        public void onGenericSoundTriggerDetected(GenericRecognitionEvent recognitionEvent) {
+        }
+
+        @Override
+        public void onKeyphraseDetected(KeyphraseRecognitionEvent recognitionEvent) {
+        }
+
+        @Override
+        public void onError(int status) {
+        }
+
+        @Override
+        public void onRecognitionPaused() {
+        }
+
+        @Override
+        public void onRecognitionResumed() {
+        }
+    }
 }
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml
new file mode 100644
index 0000000..d5d86d8
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector android:height="24dp" android:viewportHeight="400.0"
+        android:viewportWidth="1200.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillType="evenOdd"
+          android:fillColor="#f00"
+          android:pathData="M250,75L323,301 131,161 369,161 177,301z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="evenOdd"
+          android:fillColor="#f00"
+          android:pathData="M600,81A107,107 0,0 1,600 295A107,107 0,0 1,600 81zM600,139A49,49 0,0 1,600 237A49,49 0,0 1,600 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="evenOdd"
+          android:fillColor="#f00"
+          android:pathData="M950,81A107,107 0,0 1,950 295A107,107 0,0 1,950 81zM950,139A49,49 0,0 0,950 237A49,49 0,0 0,950 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml
new file mode 100644
index 0000000..9754e4b
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+-->
+<vector android:height="24dp" android:viewportHeight="400.0"
+        android:viewportWidth="1200.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillType="nonZero"
+          android:fillColor="#f00"
+          android:pathData="M250,75L323,301 131,161 369,161 177,301z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="nonZero"
+          android:fillColor="#f00"
+          android:pathData="M600,81A107,107 0,0 1,600 295A107,107 0,0 1,600 81zM600,139A49,49 0,0 1,600 237A49,49 0,0 1,600 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+    <path android:fillType="nonZero"
+          android:fillColor="#f00"
+          android:pathData="M950,81A107,107 0,0 1,950 295A107,107 0,0 1,950 81zM950,139A49,49 0,0 0,950 237A49,49 0,0 0,950 139z"
+          android:strokeColor="#000" android:strokeWidth="3"/>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
index 495d620..5856f49 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -35,6 +35,8 @@
 public class VectorDrawablePerformance extends Activity {
     private static final String LOGCAT = "VectorDrawable1";
     protected int[] icon = {
+            R.drawable.vector_icon_filltype_nonzero,
+            R.drawable.vector_icon_filltype_evenodd,
             R.drawable.vector_icon_gradient_1,
             R.drawable.vector_icon_gradient_2,
             R.drawable.vector_icon_gradient_3,
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index 57a7692..85d22ff 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -90,6 +90,7 @@
 	proto/TableProtoSerializer_test.cpp \
 	split/TableSplitter_test.cpp \
 	util/BigBuffer_test.cpp \
+	util/Files_test.cpp \
 	util/Maybe_test.cpp \
 	util/StringPiece_test.cpp \
 	util/Util_test.cpp \
@@ -124,10 +125,12 @@
 	libexpat \
 	libziparchive-host \
 	libpng \
-	libbase
+	libbase \
+	libprotobuf-cpp-lite_static
 
-hostSharedLibs := \
-	libprotobuf-cpp-lite
+# Do not add any shared libraries. AAPT2 is built to run on many
+# environments that may not have the required dependencies.
+hostSharedLibs :=
 
 ifneq ($(strip $(USE_MINGW)),)
 	hostStaticLibs += libz
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 4d1db5b..03ca42b 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -77,7 +77,7 @@
     ResourceType type;
     std::u16string entry;
 
-    ResourceName() = default;
+    ResourceName() : type(ResourceType::kRaw) {}
     ResourceName(const StringPiece16& p, ResourceType t, const StringPiece16& e);
 
     bool isValid() const;
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index b100e84..9704d970 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -81,6 +81,12 @@
 
 // Recursively adds resources to the ResourceTable.
 static bool addResourcesToTable(ResourceTable* table, IDiagnostics* diag, ParsedResource* res) {
+    StringPiece16 trimmedComment = util::trimWhitespace(res->comment);
+    if (trimmedComment.size() != res->comment.size()) {
+        // Only if there was a change do we re-assign.
+        res->comment = trimmedComment.toString();
+    }
+
     if (res->symbolState) {
         Symbol symbol;
         symbol.state = res->symbolState.value();
diff --git a/tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml b/tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml
index 2b24544..d09a485 100644
--- a/tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml
+++ b/tools/aapt2/integration-tests/StaticLibOne/res/values/values.xml
@@ -15,8 +15,13 @@
 -->
 
 <resources>
+    <!-- An attribute from StaticLibOne -->
     <attr name="StaticLibOne_attr" format="string" />
 
     <string name="Foo">Foo</string>
     <string name="Foo" product="tablet">Bar</string>
+
+    <declare-styleable name="Widget">
+        <attr name="StaticLibOne_attr" />
+    </declare-styleable>
 </resources>
diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp
index 9c25d4e..496e92e 100644
--- a/tools/aapt2/java/AnnotationProcessor.cpp
+++ b/tools/aapt2/java/AnnotationProcessor.cpp
@@ -38,7 +38,7 @@
         mComment << "/**";
     }
 
-    mComment << "\n" << " * " << std::move(comment);
+    mComment << "\n * " << std::move(comment);
 }
 
 void AnnotationProcessor::appendComment(const StringPiece16& comment) {
@@ -60,6 +60,10 @@
     }
 }
 
+void AnnotationProcessor::appendNewLine() {
+    mComment << "\n *";
+}
+
 void AnnotationProcessor::writeToStream(std::ostream* out, const StringPiece& prefix) {
     if (mHasComments) {
         std::string result = mComment.str();
diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h
index e7f2be0..fadf584 100644
--- a/tools/aapt2/java/AnnotationProcessor.h
+++ b/tools/aapt2/java/AnnotationProcessor.h
@@ -61,6 +61,8 @@
     void appendComment(const StringPiece16& comment);
     void appendComment(const StringPiece& comment);
 
+    void appendNewLine();
+
     /**
      * Writes the comments and annotations to the stream, with the given prefix before each line.
      */
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 1076ffe..01330dc 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -23,6 +23,7 @@
 #include "java/AnnotationProcessor.h"
 #include "java/ClassDefinitionWriter.h"
 #include "java/JavaClassGenerator.h"
+#include "process/SymbolTable.h"
 #include "util/StringPiece.h"
 
 #include <algorithm>
@@ -33,8 +34,9 @@
 
 namespace aapt {
 
-JavaClassGenerator::JavaClassGenerator(ResourceTable* table, JavaClassGeneratorOptions options) :
-        mTable(table), mOptions(options) {
+JavaClassGenerator::JavaClassGenerator(IAaptContext* context, ResourceTable* table,
+                                       const JavaClassGeneratorOptions& options) :
+        mContext(context), mTable(table), mOptions(options) {
 }
 
 static void generateHeader(const StringPiece16& packageNameToGenerate, std::ostream* out) {
@@ -103,6 +105,85 @@
     return output;
 }
 
+static void addAttributeFormatDoc(AnnotationProcessor* processor, Attribute* attr) {
+    const uint32_t typeMask = attr->typeMask;
+    if (typeMask & android::ResTable_map::TYPE_REFERENCE) {
+        processor->appendComment(
+                "<p>May be a reference to another resource, in the form\n"
+                        "\"<code>@[+][<i>package</i>:]<i>type</i>/<i>name</i></code>\" or a theme\n"
+                        "attribute in the form\n"
+                        "\"<code>?[<i>package</i>:]<i>type</i>/<i>name</i></code>\".");
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_STRING) {
+        processor->appendComment(
+                "<p>May be a string value, using '\\\\;' to escape characters such as\n"
+                        "'\\\\n' or '\\\\uxxxx' for a unicode character;");
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_INTEGER) {
+        processor->appendComment("<p>May be an integer value, such as \"<code>100</code>\".");
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_BOOLEAN) {
+        processor->appendComment(
+                "<p>May be a boolean value, such as \"<code>true</code>\" or\n"
+                        "\"<code>false</code>\".");
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_COLOR) {
+        processor->appendComment(
+                "<p>May be a color value, in the form of \"<code>#<i>rgb</i></code>\",\n"
+                        "\"<code>#<i>argb</i></code>\", \"<code>#<i>rrggbb</i></code\", or \n"
+                        "\"<code>#<i>aarrggbb</i></code>\".");
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_FLOAT) {
+        processor->appendComment(
+                "<p>May be a floating point value, such as \"<code>1.2</code>\".");
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_DIMENSION) {
+        processor->appendComment(
+                "<p>May be a dimension value, which is a floating point number appended with a\n"
+                        "unit such as \"<code>14.5sp</code>\".\n"
+                        "Available units are: px (pixels), dp (density-independent pixels),\n"
+                        "sp (scaled pixels based on preferred font size), in (inches), and\n"
+                        "mm (millimeters).");
+    }
+
+    if (typeMask & android::ResTable_map::TYPE_FRACTION) {
+        processor->appendComment(
+                "<p>May be a fractional value, which is a floating point number appended with\n"
+                        "either % or %p, such as \"<code>14.5%</code>\".\n"
+                        "The % suffix always means a percentage of the base size;\n"
+                        "the optional %p suffix provides a size relative to some parent container.");
+    }
+
+    if (typeMask & (android::ResTable_map::TYPE_FLAGS | android::ResTable_map::TYPE_ENUM)) {
+        if (typeMask & android::ResTable_map::TYPE_FLAGS) {
+            processor->appendComment(
+                    "<p>Must be one or more (separated by '|') of the following "
+                            "constant values.</p>");
+        } else {
+            processor->appendComment("<p>Must be one of the following constant values.</p>");
+        }
+
+        processor->appendComment("<table>\n<colgroup align=\"left\" />\n"
+                                         "<colgroup align=\"left\" />\n"
+                                         "<colgroup align=\"left\" />\n"
+                                         "<tr><th>Constant</th><th>Value</th><th>Description</th></tr>\n");
+        for (const Attribute::Symbol& symbol : attr->symbols) {
+            std::stringstream line;
+            line << "<tr><td>" << symbol.symbol.name.value().entry << "</td>"
+            << "<td>" << std::hex << symbol.value << std::dec << "</td>"
+            << "<td>" << util::trimWhitespace(symbol.symbol.getComment()) << "</td></tr>";
+            processor->appendComment(line.str());
+        }
+        processor->appendComment("</table>");
+    }
+}
+
 bool JavaClassGenerator::skipSymbol(SymbolState state) {
     switch (mOptions.types) {
     case JavaClassGeneratorOptions::SymbolTypes::kAll:
@@ -117,6 +198,7 @@
 
 struct StyleableAttr {
     const Reference* attrRef;
+    std::shared_ptr<Attribute> attribute;
     std::string fieldName;
 };
 
@@ -148,8 +230,29 @@
         assert((!mOptions.useFinal || attr.id) && "no ID set for Styleable entry");
         assert(attr.name && "no name set for Styleable entry");
 
-        sortedAttributes.emplace_back(StyleableAttr{
-                &attr, transformNestedAttr(attr.name.value(), className, packageNameToGenerate) });
+        StyleableAttr styleableAttr = {};
+        styleableAttr.attrRef = &attr;
+        styleableAttr.fieldName = transformNestedAttr(attr.name.value(), className,
+                                                      packageNameToGenerate);
+
+        Reference mangledReference;
+        mangledReference.id = attr.id;
+        mangledReference.name = attr.name;
+        if (mangledReference.name.value().package.empty()) {
+            mangledReference.name.value().package = mContext->getCompilationPackage();
+        }
+
+        if (Maybe<ResourceName> mangledName =
+                mContext->getNameMangler()->mangleName(mangledReference.name.value())) {
+            mangledReference.name = mangledName;
+        }
+
+        const SymbolTable::Symbol* symbol = mContext->getExternalSymbols()->findByReference(
+                mangledReference);
+        if (symbol) {
+            styleableAttr.attribute = symbol->attribute;
+        }
+        sortedAttributes.push_back(std::move(styleableAttr));
     }
     std::sort(sortedAttributes.begin(), sortedAttributes.end(), lessStyleableAttr);
 
@@ -159,16 +262,34 @@
         // Build the comment string for the Styleable. It includes details about the
         // child attributes.
         std::stringstream styleableComment;
-        styleableComment << "Attributes that can be used with a " << className << ".\n";
-        styleableComment << "<table>\n"
+        if (!styleable->getComment().empty()) {
+            styleableComment << styleable->getComment() << "\n";
+        } else {
+            styleableComment << "Attributes that can be used with a " << className << ".\n";
+        }
+        styleableComment <<
+                "<p>Includes the following attributes:</p>\n"
+                "<table>\n"
                 "<colgroup align=\"left\" />\n"
-                "<colgroup align=\"left\">\n"
+                "<colgroup align=\"left\" />\n"
                 "<tr><th>Attribute</th><th>Description</th></tr>\n";
+
         for (const auto& entry : sortedAttributes) {
             const ResourceName& attrName = entry.attrRef->name.value();
-            styleableComment << "<tr><td><code>{@link #" << entry.fieldName << " "
-                    << attrName.package << ":" << attrName.entry
-                    << "}</code></td><td></td></tr>\n";
+            styleableComment << "<tr><td>";
+            styleableComment << "<code>{@link #"
+                             << entry.fieldName << " "
+                             << (!attrName.package.empty()
+                                    ? attrName.package : mContext->getCompilationPackage())
+                             << ":" << attrName.entry
+                             << "}</code>";
+            styleableComment << "</td>";
+
+            styleableComment << "<td>";
+            if (entry.attribute) {
+                styleableComment << entry.attribute->getComment();
+            }
+            styleableComment << "</td></tr>\n";
         }
         styleableComment << "</table>\n";
         for (const auto& entry : sortedAttributes) {
@@ -189,96 +310,45 @@
 
     // Now we emit the indices into the array.
     for (size_t i = 0; i < attrCount; i++) {
-        const ResourceName& attrName = sortedAttributes[i].attrRef->name.value();
+        const StyleableAttr& styleableAttr = sortedAttributes[i];
+        const ResourceName& attrName = styleableAttr.attrRef->name.value();
+
+        StringPiece16 packageName = attrName.package;
+        if (packageName.empty()) {
+            packageName = mContext->getCompilationPackage();
+        }
 
         AnnotationProcessor attrProcessor;
-        std::stringstream doclavaComments;
-        doclavaComments << "@attr name ";
-        if (!attrName.package.empty()) {
-            doclavaComments << attrName.package << ":";
+
+        StringPiece16 comment = styleableAttr.attrRef->getComment();
+        if (styleableAttr.attribute && comment.empty()) {
+            comment = styleableAttr.attribute->getComment();
         }
-        doclavaComments << attrName.entry;
-        attrProcessor.appendComment(doclavaComments.str());
-        outClassDef->addIntMember(sortedAttributes[i].fieldName, &attrProcessor, i);
-    }
-}
 
-static void addAttributeFormatDoc(AnnotationProcessor* processor, Attribute* attr) {
-    const uint32_t typeMask = attr->typeMask;
-    if (typeMask & android::ResTable_map::TYPE_REFERENCE) {
-        processor->appendComment(
-                "<p>May be a reference to another resource, in the form\n"
-                "\"<code>@[+][<i>package</i>:]<i>type</i>/<i>name</i></code>\" or a theme\n"
-                "attribute in the form\n"
-                "\"<code>?[<i>package</i>:]<i>type</i>/<i>name</i></code>\".");
-    }
-
-    if (typeMask & android::ResTable_map::TYPE_STRING) {
-        processor->appendComment(
-                "<p>May be a string value, using '\\\\;' to escape characters such as\n"
-                "'\\\\n' or '\\\\uxxxx' for a unicode character;");
-    }
-
-    if (typeMask & android::ResTable_map::TYPE_INTEGER) {
-        processor->appendComment("<p>May be an integer value, such as \"<code>100</code>\".");
-    }
-
-    if (typeMask & android::ResTable_map::TYPE_BOOLEAN) {
-        processor->appendComment(
-                "<p>May be a boolean value, such as \"<code>true</code>\" or\n"
-                "\"<code>false</code>\".");
-    }
-
-    if (typeMask & android::ResTable_map::TYPE_COLOR) {
-        processor->appendComment(
-                "<p>May be a color value, in the form of \"<code>#<i>rgb</i></code>\",\n"
-                "\"<code>#<i>argb</i></code>\", \"<code>#<i>rrggbb</i></code\", or \n"
-                "\"<code>#<i>aarrggbb</i></code>\".");
-    }
-
-    if (typeMask & android::ResTable_map::TYPE_FLOAT) {
-        processor->appendComment(
-                "<p>May be a floating point value, such as \"<code>1.2</code>\".");
-    }
-
-    if (typeMask & android::ResTable_map::TYPE_DIMENSION) {
-        processor->appendComment(
-                "<p>May be a dimension value, which is a floating point number appended with a\n"
-                "unit such as \"<code>14.5sp</code>\".\n"
-                "Available units are: px (pixels), dp (density-independent pixels),\n"
-                "sp (scaled pixels based on preferred font size), in (inches), and\n"
-                "mm (millimeters).");
-    }
-
-    if (typeMask & android::ResTable_map::TYPE_FRACTION) {
-        processor->appendComment(
-                "<p>May be a fractional value, which is a floating point number appended with\n"
-                "either % or %p, such as \"<code>14.5%</code>\".\n"
-                "The % suffix always means a percentage of the base size;\n"
-                "the optional %p suffix provides a size relative to some parent container.");
-    }
-
-    if (typeMask & (android::ResTable_map::TYPE_FLAGS | android::ResTable_map::TYPE_ENUM)) {
-        if (typeMask & android::ResTable_map::TYPE_FLAGS) {
-            processor->appendComment(
-                    "<p>Must be one or more (separated by '|') of the following "
-                    "constant values.</p>");
+        if (!comment.empty()) {
+            attrProcessor.appendComment("<p>\n@attr description");
+            attrProcessor.appendComment(comment);
         } else {
-            processor->appendComment("<p>Must be one of the following constant values.</p>");
+            std::stringstream defaultComment;
+            defaultComment
+                    << "<p>This symbol is the offset where the "
+                    << "{@link " << packageName << ".R.attr#" << transform(attrName.entry) << "}\n"
+                    << "attribute's value can be found in the "
+                    << "{@link #" << className << "} array.";
+            attrProcessor.appendComment(defaultComment.str());
         }
 
-        processor->appendComment("<table>\n<colgroup align=\"left\" />\n"
-                                 "<colgroup align=\"left\" />\n"
-                                 "<colgroup align=\"left\" />\n"
-                                 "<tr><th>Constant</th><th>Value</th><th>Description</th></tr>\n");
-        for (const Attribute::Symbol& symbol : attr->symbols) {
-            std::stringstream line;
-            line << "<tr><td>" << symbol.symbol.name.value().entry << "</td>"
-                 << "<td>" << std::hex << symbol.value << std::dec << "</td>"
-                 << "<td>" << util::trimWhitespace(symbol.symbol.getComment()) << "</td></tr>";
-            processor->appendComment(line.str());
+        attrProcessor.appendNewLine();
+
+        if (styleableAttr.attribute) {
+            addAttributeFormatDoc(&attrProcessor, styleableAttr.attribute.get());
+            attrProcessor.appendNewLine();
         }
-        processor->appendComment("</table>");
+
+        std::stringstream doclavaName;
+        doclavaName << "@attr name " << packageName << ":" << attrName.entry;;
+        attrProcessor.appendComment(doclavaName.str());
+        outClassDef->addIntMember(sortedAttributes[i].fieldName, &attrProcessor, i);
     }
 }
 
diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h
index 023d6d6..7e46f8c 100644
--- a/tools/aapt2/java/JavaClassGenerator.h
+++ b/tools/aapt2/java/JavaClassGenerator.h
@@ -19,7 +19,7 @@
 
 #include "ResourceTable.h"
 #include "ResourceValues.h"
-
+#include "process/IResourceTableConsumer.h"
 #include "util/StringPiece.h"
 
 #include <ostream>
@@ -51,7 +51,8 @@
  */
 class JavaClassGenerator {
 public:
-    JavaClassGenerator(ResourceTable* table, JavaClassGeneratorOptions options);
+    JavaClassGenerator(IAaptContext* context, ResourceTable* table,
+                       const JavaClassGeneratorOptions& options);
 
     /*
      * Writes the R.java file to `out`. Only symbols belonging to `package` are written.
@@ -82,6 +83,7 @@
 
     bool skipSymbol(SymbolState state);
 
+    IAaptContext* mContext;
     ResourceTable* mTable;
     JavaClassGeneratorOptions mOptions;
     std::string mError;
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index 63d38a8..4f041b8 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -15,11 +15,9 @@
  */
 
 #include "java/JavaClassGenerator.h"
+#include "test/Test.h"
 #include "util/Util.h"
 
-#include "test/Builders.h"
-
-#include <gtest/gtest.h>
 #include <sstream>
 #include <string>
 
@@ -31,7 +29,11 @@
             .addSimple(u"@android:id/class", ResourceId(0x01020000))
             .build();
 
-    JavaClassGenerator generator(table.get(), {});
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+    JavaClassGenerator generator(context.get(), table.get(), {});
 
     std::stringstream out;
     EXPECT_FALSE(generator.generate(u"android", &out));
@@ -48,7 +50,11 @@
                               .build())
             .build();
 
-    JavaClassGenerator generator(table.get(), {});
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+    JavaClassGenerator generator(context.get(), table.get(), {});
 
     std::stringstream out;
     EXPECT_TRUE(generator.generate(u"android", &out));
@@ -72,7 +78,11 @@
             .addSimple(u"@android:id/com.foo$two", ResourceId(0x01020001))
             .build();
 
-    JavaClassGenerator generator(table.get(), {});
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+    JavaClassGenerator generator(context.get(), table.get(), {});
     std::stringstream out;
     ASSERT_TRUE(generator.generate(u"android", u"com.android.internal", &out));
 
@@ -90,7 +100,11 @@
             .addSimple(u"@android:^attr-private/one", ResourceId(0x01010000))
             .build();
 
-    JavaClassGenerator generator(table.get(), {});
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+    JavaClassGenerator generator(context.get(), table.get(), {});
     std::stringstream out;
     ASSERT_TRUE(generator.generate(u"android", &out));
 
@@ -110,10 +124,15 @@
             .setSymbolState(u"@android:id/two", ResourceId(0x01020001), SymbolState::kPrivate)
             .build();
 
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+
     JavaClassGeneratorOptions options;
     options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
     {
-        JavaClassGenerator generator(table.get(), options);
+        JavaClassGenerator generator(context.get(), table.get(), options);
         std::stringstream out;
         ASSERT_TRUE(generator.generate(u"android", &out));
         std::string output = out.str();
@@ -124,7 +143,7 @@
 
     options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
     {
-        JavaClassGenerator generator(table.get(), options);
+        JavaClassGenerator generator(context.get(), table.get(), options);
         std::stringstream out;
         ASSERT_TRUE(generator.generate(u"android", &out));
         std::string output = out.str();
@@ -135,7 +154,7 @@
 
     options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
     {
-        JavaClassGenerator generator(table.get(), options);
+        JavaClassGenerator generator(context.get(), table.get(), options);
         std::stringstream out;
         ASSERT_TRUE(generator.generate(u"android", &out));
         std::string output = out.str();
@@ -189,7 +208,11 @@
                                   .build())
                 .build();
 
-    JavaClassGenerator generator(table.get(), {});
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+    JavaClassGenerator generator(context.get(), table.get(), {});
 
     std::stringstream out;
     EXPECT_TRUE(generator.generate(u"android", &out));
@@ -207,8 +230,11 @@
     test::getValue<Id>(table.get(), u"@android:id/foo")
             ->setComment(std::u16string(u"This is a comment\n@deprecated"));
 
-    JavaClassGenerator generator(table.get(), {});
-
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
+    JavaClassGenerator generator(context.get(), table.get(), {});
     std::stringstream out;
     ASSERT_TRUE(generator.generate(u"android", &out));
     std::string actual = out.str();
@@ -241,10 +267,13 @@
                       std::unique_ptr<Styleable>(styleable.clone(nullptr)))
             .build();
 
+    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
+            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .build();
     JavaClassGeneratorOptions options;
     options.useFinal = false;
-    JavaClassGenerator generator(table.get(), options);
-
+    JavaClassGenerator generator(context.get(), table.get(), options);
     std::stringstream out;
     ASSERT_TRUE(generator.generate(u"android", &out));
     std::string actual = out.str();
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index 5003d96..b84074d 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -729,20 +729,31 @@
 
         std::string outPath = mOptions.generateJavaClassPath.value();
         file::appendPath(&outPath, file::packageToPath(util::utf16ToUtf8(outPackage)));
-        file::mkdirs(outPath);
+        if (!file::mkdirs(outPath)) {
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed to create directory '" << outPath << "'");
+            return false;
+        }
+
         file::appendPath(&outPath, "R.java");
 
         std::ofstream fout(outPath, std::ofstream::binary);
         if (!fout) {
-            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
             return false;
         }
 
-        JavaClassGenerator generator(table, javaOptions);
+        JavaClassGenerator generator(mContext, table, javaOptions);
         if (!generator.generate(packageNameToGenerate, outPackage, &fout)) {
             mContext->getDiagnostics()->error(DiagMessage(outPath) << generator.getError());
             return false;
         }
+
+        if (!fout) {
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
+        }
         return true;
     }
 
@@ -754,12 +765,18 @@
         std::string outPath = mOptions.generateJavaClassPath.value();
         file::appendPath(&outPath,
                          file::packageToPath(util::utf16ToUtf8(mContext->getCompilationPackage())));
-        file::mkdirs(outPath);
+        if (!file::mkdirs(outPath)) {
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed to create directory '" << outPath << "'");
+            return false;
+        }
+
         file::appendPath(&outPath, "Manifest.java");
 
         std::ofstream fout(outPath, std::ofstream::binary);
         if (!fout) {
-            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
             return false;
         }
 
@@ -770,7 +787,8 @@
         }
 
         if (!fout) {
-            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
             return false;
         }
         return true;
@@ -781,15 +799,18 @@
             return true;
         }
 
-        std::ofstream fout(mOptions.generateProguardRulesPath.value(), std::ofstream::binary);
+        const std::string& outPath = mOptions.generateProguardRulesPath.value();
+        std::ofstream fout(outPath, std::ofstream::binary);
         if (!fout) {
-            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed to open '" << outPath << "': " << strerror(errno));
             return false;
         }
 
         proguard::writeKeepSet(&fout, keepSet);
         if (!fout) {
-            mContext->getDiagnostics()->error(DiagMessage() << strerror(errno));
+            mContext->getDiagnostics()->error(
+                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
             return false;
         }
         return true;
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index a8f9bfe..eaaf06f 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -51,6 +51,11 @@
             // doesn't support unique_ptr.
             std::shared_ptr<Symbol> sharedSymbol = std::shared_ptr<Symbol>(symbol.release());
             mCache.put(name, sharedSymbol);
+
+            if (sharedSymbol->id) {
+                // The symbol has an ID, so we can also cache this!
+                mIdCache.put(sharedSymbol->id.value(), sharedSymbol);
+            }
             return sharedSymbol.get();
         }
     }
@@ -76,6 +81,25 @@
     return nullptr;
 }
 
+const SymbolTable::Symbol* SymbolTable::findByReference(const Reference& ref) {
+    // First try the ID. This is because when we lookup by ID, we only fill in the ID cache.
+    // Looking up by name fills in the name and ID cache. So a cache miss will cause a failed
+    // ID lookup, then a successfull name lookup. Subsequent look ups will hit immediately
+    // because the ID is cached too.
+    //
+    // If we looked up by name first, a cache miss would mean we failed to lookup by name, then
+    // succeeded to lookup by ID. Subsequent lookups will miss then hit.
+    const SymbolTable::Symbol* symbol = nullptr;
+    if (ref.id) {
+        symbol = findById(ref.id.value());
+    }
+
+    if (ref.name && !symbol) {
+        symbol = findByName(ref.name.value());
+    }
+    return symbol;
+}
+
 std::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::findByName(
         const ResourceName& name) {
     Maybe<ResourceTable::SearchResult> result = mTable->findResource(name);
@@ -102,7 +126,7 @@
         if (configValue) {
             // This resource has an Attribute.
             if (Attribute* attr = valueCast<Attribute>(configValue->value.get())) {
-                symbol->attribute = util::make_unique<Attribute>(*attr);
+                symbol->attribute = std::make_shared<Attribute>(*attr);
             } else {
                 return {};
             }
@@ -133,7 +157,7 @@
     // Check to see if it is an attribute.
     for (size_t i = 0; i < (size_t) count; i++) {
         if (entry[i].map.name.ident == android::ResTable_map::ATTR_TYPE) {
-            s->attribute = util::make_unique<Attribute>(false);
+            s->attribute = std::make_shared<Attribute>(false);
             s->attribute->typeMask = entry[i].map.value.data;
             break;
         }
@@ -272,4 +296,15 @@
     return {};
 }
 
+std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::findByReference(
+        const Reference& ref) {
+    // AssetManager always prefers IDs.
+    if (ref.id) {
+        return findById(ref.id.value());
+    } else if (ref.name) {
+        return findByName(ref.name.value());
+    }
+    return {};
+}
+
 } // namespace aapt
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index 8ea1c75..0a6a4a5 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -52,7 +52,7 @@
 public:
     struct Symbol {
         Maybe<ResourceId> id;
-        std::unique_ptr<Attribute> attribute;
+        std::shared_ptr<Attribute> attribute;
         bool isPublic;
     };
 
@@ -69,6 +69,12 @@
     const Symbol* findByName(const ResourceName& name);
     const Symbol* findById(ResourceId id);
 
+    /**
+     * Let's the ISymbolSource decide whether looking up by name or ID is faster, if both
+     * are available.
+     */
+    const Symbol* findByReference(const Reference& ref);
+
 private:
     std::vector<std::unique_ptr<ISymbolSource>> mSources;
 
@@ -90,6 +96,18 @@
 
     virtual std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) = 0;
     virtual std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) = 0;
+
+    /**
+     * Default implementation tries the name if it exists, else the ID.
+     */
+    virtual std::unique_ptr<SymbolTable::Symbol> findByReference(const Reference& ref) {
+        if (ref.name) {
+            return findByName(ref.name.value());
+        } else if (ref.id) {
+            return findById(ref.id.value());
+        }
+        return {};
+    }
 };
 
 /**
@@ -122,6 +140,7 @@
 
     std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override;
     std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override;
+    std::unique_ptr<SymbolTable::Symbol> findByReference(const Reference& ref) override;
 
 private:
     android::AssetManager mAssets;
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index 04e8199..6428e98 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -96,7 +96,7 @@
     const char* start = path.begin();
     const char* end = path.end();
     for (const char* current = start; current != end; ++current) {
-        if (*current == sDirSep) {
+        if (*current == sDirSep && current != start) {
             StringPiece parentPath(start, current - start);
             int result = mkdirImpl(parentPath);
             if (result < 0 && errno != EEXIST) {
@@ -139,6 +139,20 @@
     return {};
 }
 
+void appendPath(std::string* base, StringPiece part) {
+    assert(base);
+    const bool baseHasTrailingSep = (!base->empty() && *(base->end() - 1) == sDirSep);
+    const bool partHasLeadingSep = (!part.empty() && *(part.begin()) == sDirSep);
+    if (baseHasTrailingSep && partHasLeadingSep) {
+        // Remove the part's leading sep
+        part = part.substr(1, part.size() - 1);
+    } else if (!baseHasTrailingSep && !partHasLeadingSep) {
+        // None of the pieces has a separator.
+        *base += sDirSep;
+    }
+    base->append(part.data(), part.size());
+}
+
 std::string packageToPath(const StringPiece& package) {
     std::string outPath;
     for (StringPiece part : util::tokenize<char>(package, '.')) {
diff --git a/tools/aapt2/util/Files.h b/tools/aapt2/util/Files.h
index c58ba5d..c2e6115 100644
--- a/tools/aapt2/util/Files.h
+++ b/tools/aapt2/util/Files.h
@@ -61,14 +61,7 @@
 /*
  * Appends a path to `base`, separated by the directory separator.
  */
-void appendPath(std::string* base, const StringPiece& part);
-
-/*
- * Appends a series of paths to `base`, separated by the
- * system directory separator.
- */
-template <typename... Ts >
-void appendPath(std::string* base, const StringPiece& part, const Ts&... parts);
+void appendPath(std::string* base, StringPiece part);
 
 /*
  * Makes all the directories in `path`. The last element in the path
@@ -139,20 +132,6 @@
     std::vector<std::string> mPatternTokens;
 };
 
-inline void appendPath(std::string* base, const StringPiece& part) {
-    assert(base);
-    *base += sDirSep;
-    base->append(part.data(), part.size());
-}
-
-template <typename... Ts >
-void appendPath(std::string* base, const StringPiece& part, const Ts&... parts) {
-    assert(base);
-    *base += sDirSep;
-    base->append(part.data(), part.size());
-    appendPath(base, parts...);
-}
-
 } // namespace file
 } // namespace aapt
 
diff --git a/tools/aapt2/util/Files_test.cpp b/tools/aapt2/util/Files_test.cpp
new file mode 100644
index 0000000..efb0459
--- /dev/null
+++ b/tools/aapt2/util/Files_test.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2016 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 "test/Test.h"
+#include "util/Files.h"
+
+#include <sstream>
+
+namespace aapt {
+namespace file {
+
+class FilesTest : public ::testing::Test {
+public:
+    void SetUp() override {
+        std::stringstream builder;
+        builder << "hello" << sDirSep << "there";
+        mExpectedPath = builder.str();
+    }
+
+protected:
+    std::string mExpectedPath;
+};
+
+TEST_F(FilesTest, appendPath) {
+    std::string base = "hello";
+    appendPath(&base, "there");
+    EXPECT_EQ(mExpectedPath, base);
+}
+
+TEST_F(FilesTest, appendPathWithLeadingOrTrailingSeparators) {
+    std::string base = "hello/";
+    appendPath(&base, "there");
+    EXPECT_EQ(mExpectedPath, base);
+
+    base = "hello";
+    appendPath(&base, "/there");
+    EXPECT_EQ(mExpectedPath, base);
+
+    base = "hello/";
+    appendPath(&base, "/there");
+    EXPECT_EQ(mExpectedPath, base);
+}
+
+} // namespace files
+} // namespace aapt
diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py
new file mode 100755
index 0000000..fb172d4
--- /dev/null
+++ b/tools/fonts/fontchain_lint.py
@@ -0,0 +1,240 @@
+#!/usr/bin/env python
+
+import collections
+import glob
+from os import path
+import sys
+from xml.etree import ElementTree
+
+from fontTools import ttLib
+
+LANG_TO_SCRIPT = {
+    'de': 'Latn',
+    'en': 'Latn',
+    'es': 'Latn',
+    'eu': 'Latn',
+    'ja': 'Jpan',
+    'ko': 'Kore',
+    'hu': 'Latn',
+    'hy': 'Armn',
+    'nb': 'Latn',
+    'nn': 'Latn',
+    'pt': 'Latn',
+}
+
+def lang_to_script(lang_code):
+    lang = lang_code.lower()
+    while lang not in LANG_TO_SCRIPT:
+        hyphen_idx = lang.rfind('-')
+        assert hyphen_idx != -1, (
+            'We do not know what script the "%s" language is written in.'
+            % lang_code)
+        assumed_script = lang[hyphen_idx+1:]
+        if len(assumed_script) == 4 and assumed_script.isalpha():
+            # This is actually the script
+            return assumed_script.title()
+        lang = lang[:hyphen_idx]
+    return LANG_TO_SCRIPT[lang]
+
+
+def get_best_cmap(font):
+    font_file, index = font
+    font_path = path.join(_fonts_dir, font_file)
+    if index is not None:
+        ttfont = ttLib.TTFont(font_path, fontNumber=index)
+    else:
+        ttfont = ttLib.TTFont(font_path)
+    all_unicode_cmap = None
+    bmp_cmap = None
+    for cmap in ttfont['cmap'].tables:
+        specifier = (cmap.format, cmap.platformID, cmap.platEncID)
+        if specifier == (4, 3, 1):
+            assert bmp_cmap is None, 'More than one BMP cmap in %s' % (font, )
+            bmp_cmap = cmap
+        elif specifier == (12, 3, 10):
+            assert all_unicode_cmap is None, (
+                'More than one UCS-4 cmap in %s' % (font, ))
+            all_unicode_cmap = cmap
+
+    return all_unicode_cmap.cmap if all_unicode_cmap else bmp_cmap.cmap
+
+
+def assert_font_supports_any_of_chars(font, chars):
+    best_cmap = get_best_cmap(font)
+    for char in chars:
+        if char in best_cmap:
+            return
+    sys.exit('None of characters in %s were found in %s' % (chars, font))
+
+
+def assert_font_supports_all_of_chars(font, chars):
+    best_cmap = get_best_cmap(font)
+    for char in chars:
+        assert char in best_cmap, (
+            'U+%04X was not found in %s' % (char, font))
+
+
+def assert_font_supports_none_of_chars(font, chars):
+    best_cmap = get_best_cmap(font)
+    for char in chars:
+        assert char not in best_cmap, (
+            'U+%04X was found in %s' % (char, font))
+
+
+def check_hyphens(hyphens_dir):
+    # Find all the scripts that need automatic hyphenation
+    scripts = set()
+    for hyb_file in glob.iglob(path.join(hyphens_dir, '*.hyb')):
+        hyb_file = path.basename(hyb_file)
+        assert hyb_file.startswith('hyph-'), (
+            'Unknown hyphenation file %s' % hyb_file)
+        lang_code = hyb_file[hyb_file.index('-')+1:hyb_file.index('.')]
+        scripts.add(lang_to_script(lang_code))
+
+    HYPHENS = {0x002D, 0x2010}
+    for script in scripts:
+        fonts = _script_to_font_map[script]
+        assert fonts, 'No fonts found for the "%s" script' % script
+        for font in fonts:
+            assert_font_supports_any_of_chars(font, HYPHENS)
+
+
+def parse_fonts_xml(fonts_xml_path):
+    global _script_to_font_map, _fallback_chain
+    _script_to_font_map = collections.defaultdict(set)
+    _fallback_chain = []
+    tree = ElementTree.parse(fonts_xml_path)
+    for family in tree.findall('family'):
+        name = family.get('name')
+        variant = family.get('variant')
+        langs = family.get('lang')
+        if name:
+            assert variant is None, (
+                'No variant expected for LGC font %s.' % name)
+            assert langs is None, (
+                'No language expected for LGC fonts %s.' % name)
+        else:
+            assert variant in {None, 'elegant', 'compact'}, (
+                'Unexpected value for variant: %s' % variant)
+
+        if langs:
+            langs = langs.split()
+            scripts = {lang_to_script(lang) for lang in langs}
+        else:
+            scripts = set()
+
+        for child in family:
+            assert child.tag == 'font', (
+                'Unknown tag <%s>' % child.tag)
+            font_file = child.text
+            weight = int(child.get('weight'))
+            assert weight % 100 == 0, (
+                'Font weight "%d" is not a multiple of 100.' % weight)
+
+            style = child.get('style')
+            assert style in {'normal', 'italic'}, (
+                'Unknown style "%s"' % style)
+
+            index = child.get('index')
+            if index:
+                index = int(index)
+
+            _fallback_chain.append((
+                name,
+                frozenset(scripts),
+                variant,
+                weight,
+                style,
+                (font_file, index)))
+
+            if name: # non-empty names are used for default LGC fonts
+                map_scripts = {'Latn', 'Grek', 'Cyrl'}
+            else:
+                map_scripts = scripts
+            for script in map_scripts:
+                _script_to_font_map[script].add((font_file, index))
+
+
+def check_emoji_availability():
+    emoji_fonts = [font[5] for font in _fallback_chain if 'Zsye' in font[1]]
+    emoji_chars = _emoji_properties['Emoji']
+    for emoji_font in emoji_fonts:
+        assert_font_supports_all_of_chars(emoji_font, emoji_chars)
+
+
+def check_emoji_defaults():
+    default_emoji_chars = _emoji_properties['Emoji_Presentation']
+    emoji_font_seen = False
+    for name, scripts, variant, weight, style, font in _fallback_chain:
+        if 'Zsye' in scripts:
+            emoji_font_seen = True
+            # No need to check the emoji font
+            continue
+        # For later fonts, we only check them if they have a script
+        # defined, since the defined script may get them to a higher
+        # score even if they appear after the emoji font.
+        if emoji_font_seen and not scripts:
+            continue
+
+        if font[1] is None:
+            emoji_to_skip = set()
+        else:
+            # CJK font, skip checking the following characters for now.
+            # See b/26153752
+            emoji_to_skip = ({
+                0x26BD, # SOCCER BALL
+                0x26BE, # BASEBALL
+                0x1F18E, # NEGATIVE SQUARED AB
+                0x1F201, # SQUARED KATAKANA KOKO
+                0x1F21A, # SQUARED CJK UNIFIED IDEOGRAPH-7121
+                0x1F22F, # SQUARED CJK UNIFIED IDEOGRAPH-6307
+            } | set(xrange(0x1F191, 0x1F19A+1))
+              | set(xrange(0x1F232, 0x1F236+1))
+              | set(xrange(0x1F238, 0x1F23A+1))
+              | set(xrange(0x1F250, 0x1F251+1)))
+
+        assert_font_supports_none_of_chars(font,
+            sorted(default_emoji_chars - emoji_to_skip))
+
+
+def parse_ucd(ucd_path):
+    global _emoji_properties
+    _emoji_properties = collections.defaultdict(set)
+    with open(path.join(ucd_path, 'emoji-data.txt')) as emoji_data_txt:
+        for line in emoji_data_txt:
+            if '#' in line:
+                line = line[:line.index('#')]
+            line = line.strip()
+            if not line:
+                continue
+            char_range, prop = line.split(';')
+            char_range = char_range.strip()
+            prop = prop.strip()
+            if '..' in char_range:
+                char_start, char_end = char_range.split('..')
+            else:
+                char_start = char_end = char_range
+            char_start = int(char_start, 16)
+            char_end = int(char_end, 16)
+            _emoji_properties[prop].update(xrange(char_start, char_end+1))
+
+
+def main():
+    target_out = sys.argv[1]
+    global _fonts_dir
+    _fonts_dir = path.join(target_out, 'fonts')
+
+    fonts_xml_path = path.join(target_out, 'etc', 'fonts.xml')
+    parse_fonts_xml(fonts_xml_path)
+
+    hyphens_dir = path.join(target_out, 'usr', 'hyphen-data')
+    check_hyphens(hyphens_dir)
+
+    ucd_path = sys.argv[2]
+    parse_ucd(ucd_path)
+    check_emoji_availability()
+    check_emoji_defaults()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index e3bb3e3..6d8ecd7 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -67,7 +67,7 @@
 
     // ---- delegate manager ----
     private static final DelegateManager<Bitmap_Delegate> sManager =
-            new DelegateManager<Bitmap_Delegate>(Bitmap_Delegate.class);
+            new DelegateManager<>(Bitmap_Delegate.class);
     private static long sFinalizer = -1;
 
     // ---- delegate helper data ----
@@ -314,7 +314,7 @@
 
     @LayoutlibDelegate
     /*package*/ static boolean nativeRecycle(long nativeBitmap) {
-        sManager.removeJavaReferenceFor(nativeBitmap);
+        // In our case reycle() is a no-op. We will let the finalizer to dispose the bitmap.
         return true;
     }
 
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 97195e4..7f41348 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -492,8 +492,7 @@
     }
 
     @Override
-    public void keyguardGoingAway(boolean disableWindowAnimations,
-            boolean keyguardGoingToNotificationShade) throws RemoteException {
+    public void keyguardGoingAway(int flags) throws RemoteException {
     }
 
     @Override
@@ -561,6 +560,10 @@
     }
 
     @Override
+    public void setDockedStackDividerTouchRegion(Rect touchableRegion) throws RemoteException {
+    }
+
+    @Override
     public void requestAppKeyboardShortcuts(IResultReceiver receiver) throws RemoteException {
     }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 4039cdf..42c0ae0 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -715,6 +715,10 @@
     }
 
     @Override
+    public void flushPackageRestrictionsAsUser(int userId) {
+    }
+
+    @Override
     public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
             UserHandle userHandle) {
         return false;
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index 13abaff..87fc7fa 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -1,5 +1,6 @@
 package android.net.wifi;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.content.Context;
 import android.os.Bundle;
@@ -14,6 +15,7 @@
 import android.util.Log;
 import android.util.SparseArray;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 
@@ -275,12 +277,13 @@
         /** Implement the Parcelable interface {@hide} */
         public static final Creator<RttCapabilities> CREATOR =
             new Creator<RttCapabilities>() {
-               public RttCapabilities createFromParcel(Parcel in) {
+            @Override
+            public RttCapabilities createFromParcel(Parcel in) {
                     RttCapabilities capabilities = new RttCapabilities();
-                    capabilities.oneSidedRttSupported = in.readInt() == 1 ? true : false;
-                        capabilities.twoSided11McRttSupported = in.readInt() == 1 ? true : false;
-                        capabilities.lciSupported = in.readInt() == 1 ? true : false;
-                        capabilities.lcrSupported = in.readInt() == 1 ? true : false;
+                    capabilities.oneSidedRttSupported = (in.readInt() == 1);
+                        capabilities.twoSided11McRttSupported = (in.readInt() == 1);
+                        capabilities.lciSupported = (in.readInt() == 1);
+                        capabilities.lcrSupported = (in.readInt() == 1);
                         capabilities.preambleSupported = in.readInt();
                         capabilities.bwSupported = in.readInt();
                         capabilities.responderSupported = (in.readInt() == 1);
@@ -464,58 +467,57 @@
     /** pseudo-private class used to parcel arguments */
     public static class ParcelableRttParams implements Parcelable {
 
+        @NonNull
         public RttParams mParams[];
 
-        ParcelableRttParams(RttParams[] params) {
-            mParams = params;
+        /**
+         * @hide
+         */
+        @VisibleForTesting
+        public ParcelableRttParams(RttParams[] params) {
+            mParams = (params == null ? new RttParams[0] : params);
         }
 
         /** Implement the Parcelable interface {@hide} */
+        @Override
         public int describeContents() {
             return 0;
         }
 
         /** Implement the Parcelable interface {@hide} */
+        @Override
         public void writeToParcel(Parcel dest, int flags) {
-            if (mParams != null) {
-                dest.writeInt(mParams.length);
+            dest.writeInt(mParams.length);
 
-                for (RttParams params : mParams) {
-                    dest.writeInt(params.deviceType);
-                    dest.writeInt(params.requestType);
-                    dest.writeByte(params.secure ? (byte) 1 : 0);
-                    dest.writeString(params.bssid);
-                    dest.writeInt(params.channelWidth);
-                    dest.writeInt(params.frequency);
-                    dest.writeInt(params.centerFreq0);
-                    dest.writeInt(params.centerFreq1);
-                    dest.writeInt(params.numberBurst);
-                    dest.writeInt(params.interval);
-                    dest.writeInt(params.numSamplesPerBurst);
-                    dest.writeInt(params.numRetriesPerMeasurementFrame);
-                    dest.writeInt(params.numRetriesPerFTMR);
-                    dest.writeInt(params.LCIRequest ? 1 : 0);
-                    dest.writeInt(params.LCRRequest ? 1 : 0);
-                    dest.writeInt(params.burstTimeout);
-                    dest.writeInt(params.preamble);
-                    dest.writeInt(params.bandwidth);
-                }
-            } else {
-                dest.writeInt(0);
+            for (RttParams params : mParams) {
+                dest.writeInt(params.deviceType);
+                dest.writeInt(params.requestType);
+                dest.writeByte(params.secure ? (byte) 1 : 0);
+                dest.writeString(params.bssid);
+                dest.writeInt(params.channelWidth);
+                dest.writeInt(params.frequency);
+                dest.writeInt(params.centerFreq0);
+                dest.writeInt(params.centerFreq1);
+                dest.writeInt(params.numberBurst);
+                dest.writeInt(params.interval);
+                dest.writeInt(params.numSamplesPerBurst);
+                dest.writeInt(params.numRetriesPerMeasurementFrame);
+                dest.writeInt(params.numRetriesPerFTMR);
+                dest.writeInt(params.LCIRequest ? 1 : 0);
+                dest.writeInt(params.LCRRequest ? 1 : 0);
+                dest.writeInt(params.burstTimeout);
+                dest.writeInt(params.preamble);
+                dest.writeInt(params.bandwidth);
             }
         }
 
         /** Implement the Parcelable interface {@hide} */
         public static final Creator<ParcelableRttParams> CREATOR =
                 new Creator<ParcelableRttParams>() {
+                    @Override
                     public ParcelableRttParams createFromParcel(Parcel in) {
 
                         int num = in.readInt();
-
-                        if (num == 0) {
-                            return new ParcelableRttParams(null);
-                        }
-
                         RttParams params[] = new RttParams[num];
                         for (int i = 0; i < num; i++) {
                             params[i] = new RttParams();
@@ -532,8 +534,8 @@
                             params[i].numSamplesPerBurst = in.readInt();
                             params[i].numRetriesPerMeasurementFrame = in.readInt();
                             params[i].numRetriesPerFTMR = in.readInt();
-                            params[i].LCIRequest = in.readInt() == 1 ? true : false;
-                            params[i].LCRRequest = in.readInt() == 1 ? true : false;
+                            params[i].LCIRequest = (in.readInt() == 1);
+                            params[i].LCRRequest = (in.readInt() == 1);
                             params[i].burstTimeout = in.readInt();
                             params[i].preamble = in.readInt();
                             params[i].bandwidth = in.readInt();
@@ -543,6 +545,7 @@
                         return parcelableParams;
                     }
 
+                    @Override
                     public ParcelableRttParams[] newArray(int size) {
                         return new ParcelableRttParams[size];
                     }
@@ -715,11 +718,13 @@
         }
 
         /** Implement the Parcelable interface {@hide} */
+        @Override
         public int describeContents() {
             return 0;
         }
 
         /** Implement the Parcelable interface {@hide} */
+        @Override
         public void writeToParcel(Parcel dest, int flags) {
             if (mResults != null) {
                 dest.writeInt(mResults.length);
@@ -764,6 +769,7 @@
         /** Implement the Parcelable interface {@hide} */
         public static final Creator<ParcelableRttResults> CREATOR =
                 new Creator<ParcelableRttResults>() {
+                    @Override
                     public ParcelableRttResults createFromParcel(Parcel in) {
 
                         int num = in.readInt();
@@ -816,6 +822,7 @@
                         return parcelableResults;
                     }
 
+                    @Override
                     public ParcelableRttResults[] newArray(int size) {
                         return new ParcelableRttResults[size];
                     }
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index a5bfd3c..823fd26 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -21,7 +21,6 @@
 import android.annotation.SystemApi;
 import android.content.Context;
 import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
 import android.net.DhcpInfo;
 import android.net.Network;
 import android.net.NetworkCapabilities;
@@ -666,17 +665,15 @@
     private final int mTargetSdkVersion;
 
     private static final int INVALID_KEY = 0;
-    private static int sListenerKey = 1;
-    private static final SparseArray sListenerMap = new SparseArray();
-    private static final Object sListenerMapLock = new Object();
+    private int mListenerKey = 1;
+    private final SparseArray mListenerMap = new SparseArray();
+    private final Object mListenerMapLock = new Object();
 
-    private static AsyncChannel sAsyncChannel;
-    private static CountDownLatch sConnected;
-    private static ConnectivityManager sCM;
+    private AsyncChannel mAsyncChannel;
+    private CountDownLatch mConnected;
 
-    private static final Object sThreadRefLock = new Object();
-    private static int sThreadRefCount;
-    private static HandlerThread sHandlerThread;
+    /* TODO(b/27432949): Use a common connectivity thread for this. */
+    private HandlerThread mHandlerThread;
 
     /**
      * Create a new WifiManager instance.
@@ -1482,7 +1479,7 @@
      */
     public void getTxPacketCount(TxPacketCountListener listener) {
         validateChannel();
-        sAsyncChannel.sendMessage(RSSI_PKTCNT_FETCH, 0, putListener(listener));
+        mAsyncChannel.sendMessage(RSSI_PKTCNT_FETCH, 0, putListener(listener));
     }
 
     /**
@@ -1846,25 +1843,34 @@
         public void onFailure(int reason);
     }
 
-    private static class ServiceHandler extends Handler {
+    // Ensure that multiple ServiceHandler threads do not interleave message dispatch.
+    private static final Object sServiceHandlerDispatchLock = new Object();
+
+    private class ServiceHandler extends Handler {
         ServiceHandler(Looper looper) {
             super(looper);
         }
 
         @Override
         public void handleMessage(Message message) {
+            synchronized (sServiceHandlerDispatchLock) {
+                dispatchMessageToListeners(message);
+            }
+        }
+
+        private void dispatchMessageToListeners(Message message) {
             Object listener = removeListener(message.arg2);
             switch (message.what) {
                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
                     if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
-                        sAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+                        mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
                     } else {
                         Log.e(TAG, "Failed to set up channel connection");
                         // This will cause all further async API calls on the WifiManager
                         // to fail and throw an exception
-                        sAsyncChannel = null;
+                        mAsyncChannel = null;
                     }
-                    sConnected.countDown();
+                    mConnected.countDown();
                     break;
                 case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
                     // Ignore
@@ -1873,7 +1879,7 @@
                     Log.e(TAG, "Channel connection lost");
                     // This will cause all further async API calls on the WifiManager
                     // to fail and throw an exception
-                    sAsyncChannel = null;
+                    mAsyncChannel = null;
                     getLooper().quit();
                     break;
                     /* ActionListeners grouped together */
@@ -1899,8 +1905,8 @@
                         WpsResult result = (WpsResult) message.obj;
                         ((WpsCallback) listener).onStarted(result.pin);
                         //Listener needs to stay until completion or failure
-                        synchronized(sListenerMapLock) {
-                            sListenerMap.put(message.arg2, listener);
+                        synchronized (mListenerMapLock) {
+                            mListenerMap.put(message.arg2, listener);
                         }
                     }
                     break;
@@ -1945,54 +1951,50 @@
         }
     }
 
-    private static int putListener(Object listener) {
+    private int putListener(Object listener) {
         if (listener == null) return INVALID_KEY;
         int key;
-        synchronized (sListenerMapLock) {
+        synchronized (mListenerMapLock) {
             do {
-                key = sListenerKey++;
+                key = mListenerKey++;
             } while (key == INVALID_KEY);
-            sListenerMap.put(key, listener);
+            mListenerMap.put(key, listener);
         }
         return key;
     }
 
-    private static Object removeListener(int key) {
+    private Object removeListener(int key) {
         if (key == INVALID_KEY) return null;
-        synchronized (sListenerMapLock) {
-            Object listener = sListenerMap.get(key);
-            sListenerMap.remove(key);
+        synchronized (mListenerMapLock) {
+            Object listener = mListenerMap.get(key);
+            mListenerMap.remove(key);
             return listener;
         }
     }
 
     private void init() {
-        synchronized (sThreadRefLock) {
-            if (++sThreadRefCount == 1) {
-                Messenger messenger = getWifiServiceMessenger();
-                if (messenger == null) {
-                    sAsyncChannel = null;
-                    return;
-                }
+        Messenger messenger = getWifiServiceMessenger();
+        if (messenger == null) {
+            mAsyncChannel = null;
+            return;
+        }
 
-                sHandlerThread = new HandlerThread("WifiManager");
-                sAsyncChannel = new AsyncChannel();
-                sConnected = new CountDownLatch(1);
+        mHandlerThread = new HandlerThread("WifiManager");
+        mAsyncChannel = new AsyncChannel();
+        mConnected = new CountDownLatch(1);
 
-                sHandlerThread.start();
-                Handler handler = new ServiceHandler(sHandlerThread.getLooper());
-                sAsyncChannel.connect(mContext, handler, messenger);
-                try {
-                    sConnected.await();
-                } catch (InterruptedException e) {
-                    Log.e(TAG, "interrupted wait at init");
-                }
-            }
+        mHandlerThread.start();
+        Handler handler = new ServiceHandler(mHandlerThread.getLooper());
+        mAsyncChannel.connect(mContext, handler, messenger);
+        try {
+            mConnected.await();
+        } catch (InterruptedException e) {
+            Log.e(TAG, "interrupted wait at init");
         }
     }
 
     private void validateChannel() {
-        if (sAsyncChannel == null) throw new IllegalStateException(
+        if (mAsyncChannel == null) throw new IllegalStateException(
                 "No permission to access and change wifi or a bad initialization");
     }
 
@@ -2017,7 +2019,7 @@
         validateChannel();
         // Use INVALID_NETWORK_ID for arg1 when passing a config object
         // arg1 is used to pass network id when the network already exists
-        sAsyncChannel.sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,
+        mAsyncChannel.sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,
                 putListener(listener), config);
     }
 
@@ -2037,7 +2039,7 @@
     public void connect(int networkId, ActionListener listener) {
         if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         validateChannel();
-        sAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
+        mAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
     }
 
     /**
@@ -2061,7 +2063,7 @@
     public void save(WifiConfiguration config, ActionListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
         validateChannel();
-        sAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
+        mAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
     }
 
     /**
@@ -2080,7 +2082,7 @@
     public void forget(int netId, ActionListener listener) {
         if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         validateChannel();
-        sAsyncChannel.sendMessage(FORGET_NETWORK, netId, putListener(listener));
+        mAsyncChannel.sendMessage(FORGET_NETWORK, netId, putListener(listener));
     }
 
     /**
@@ -2095,7 +2097,7 @@
     public void disable(int netId, ActionListener listener) {
         if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
         validateChannel();
-        sAsyncChannel.sendMessage(DISABLE_NETWORK, netId, putListener(listener));
+        mAsyncChannel.sendMessage(DISABLE_NETWORK, netId, putListener(listener));
     }
 
     /**
@@ -2124,7 +2126,7 @@
     public void startWps(WpsInfo config, WpsCallback listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
         validateChannel();
-        sAsyncChannel.sendMessage(START_WPS, 0, putListener(listener), config);
+        mAsyncChannel.sendMessage(START_WPS, 0, putListener(listener), config);
     }
 
     /**
@@ -2136,7 +2138,7 @@
      */
     public void cancelWps(WpsCallback listener) {
         validateChannel();
-        sAsyncChannel.sendMessage(CANCEL_WPS, 0, putListener(listener));
+        mAsyncChannel.sendMessage(CANCEL_WPS, 0, putListener(listener));
     }
 
     /**
@@ -2601,10 +2603,8 @@
 
     protected void finalize() throws Throwable {
         try {
-            synchronized (sThreadRefLock) {
-                if (--sThreadRefCount == 0 && sAsyncChannel != null) {
-                    sAsyncChannel.disconnect();
-                }
+            if (mAsyncChannel != null) {
+                mAsyncChannel.disconnect();
             }
         } finally {
             super.finalize();